package com.zc.api.controller;

import java.util.List;

import com.zc.operator.domain.ChargeStationPrice;

import java.util.Date;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipayEncrypt;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.ReactiveResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.ip.AddressUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.zc.api.domain.ApsmsResult;
import com.zc.api.domain.IotDeviceAssociation;
import com.zc.api.domain.TestDomain;
import com.zc.api.util.HttpClientSslUtils;
import com.zc.api.util.JsonUtil;
import com.zc.api.util.WXUtils;
import com.zc.common.constant.RedisKeyConstants;
import com.zc.common.core.websocket.WebSocketService;
import com.zc.common.core.websocket.constant.WebSocketEvent;
import com.zc.custom.domain.*;
import com.zc.custom.mapper.*;
import com.zc.custom.service.IChargeCustomOrderInfoService;
import com.zc.custom.service.IChargeOtherOrderInfoService;
import com.zc.iotDevice.domain.*;
import com.zc.iotDevice.mapper.ChargeFaultMapper;
import com.zc.iotDevice.mapper.ChargeStationPileMapper;
import com.zc.iotDevice.mapper.ChargeStationPortMapper;
import com.zc.iotDevice.mapper.IotDeviceSubsidiaryMapper;
import com.zc.iotDevice.service.ChargeStationPortService;
import com.zc.manager.device.domain.IotDevice;
import com.zc.manager.device.entity.DeviceProperty;
import com.zc.manager.device.service.IIotDeviceService;
import com.zc.manager.device.service.data.DeviceDataService;
import com.zc.manager.device.service.impl.IotDeviceServiceImpl;
import com.zc.operator.domain.*;
import com.zc.operator.mapper.*;
import com.zc.operator.service.ChargeStationPriceTacticsService;
import com.zc.remoteControl.service.RemoteInstructSendService;
import com.zc.trendsDispatch.domain.ChargePileOrderInfo;
import com.zc.trendsDispatch.mapper.ChargePileOrderInfoMapper;
import com.zc.web.api.crud.entity.PagerResult;
import com.zc.web.api.crud.entity.QueryParamEntity;
import com.zc.wxPay.domain.WxPay;
import com.zc.wxPay.service.WXPayService;
import com.zc.wxPay.util.AlipayConfig;
import com.zc.wxPay.util.Configure;
import io.vertx.core.json.Json;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.logging.log4j.spi.ObjectThreadContextMap;
import org.aspectj.weaver.loadtime.Aj;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.checkerframework.checker.units.qual.A;
import org.hswebframework.ezorm.core.param.Sort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.Disposable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.crypto.Data;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author:gaojikun
 * @Date:2023-05-18 16:50
 * @Description:API接口 无需登录
 */
@RestController
@RequestMapping("/api")
public class APIController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);

    @Autowired
    private DeviceDataService deviceDataService;//设备

    @Autowired
    private IIotDeviceService iiotDeviceService;//设备

    @Autowired
    private IotDeviceServiceImpl iotDeviceService;//设备

    @Autowired
    private ChargeCustomUserMapper chargeCustomUserMapper;//用户

    @Autowired
    private ChargeStationMapper chargeStationMapper;//站点

    @Autowired
    private ChargeStationPriceMapper chargeStationPriceMapper;//价格

    @Autowired
    ChargeStationAdjustPriceMapper chargeStationAdjustPriceMapper;

    @Autowired
    private ChargeStationPriceTacticsMapper chargeStationPriceTacticsMapper;//价格

    @Autowired
    private IotDeviceSubsidiaryMapper iotDeviceSubsidiaryMapper;//设备

    @Autowired
    private ChargeCarMapper chargeCarMapper;//用户车辆

    @Autowired
    private ChargeCustomOrderInfoMapper chargeCustomOrderInfoMapper;//用户订单

    @Autowired
    private ChargeCustomOrderInvoiceMapper chargeCustomOrderInvoiceMapper;//发票

    @Autowired
    private ChargeFaultMapper chargeFaultMapper;//故障

    @Autowired
    private ChargeCustomOrderEvaluationMapper chargeCustomOrderEvaluationMapper;//评价

    @Autowired
    private ChargeStationPriceTacticsService chargeStationPriceTacticsService;//策略

    @Autowired
    private ChargeStationPileMapper chargeStationPileMapper;//充电桩

    @Autowired
    private ChargeStationPortMapper chargeStationPortMapper;//充电枪

    @Autowired
    private ChargeStationPortService chargeStationPortService;//充电枪

    @Resource
    private RemoteInstructSendService remoteInstructSendService;//指令

    @Resource
    private ChargePileOrderInfoMapper chargePileOrderInfoMapper;

    @Resource
    private ChargeOtherOrderInfoMapper chargeOtherOrderInfoMapper;

    @Resource
    private WXPayService wXPayService;//微信支付

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SysLoginService loginService;

    @Resource
    private IChargeCustomOrderInfoService chargeCustomOrderInfoService;//用户订单Service接口

    @Resource
    private IChargeOtherOrderInfoService chargeOtherOrderInfoService;//第三方订单表

    @GetMapping("/getAPPInfo")
    public AjaxResult getAPPInfo(String code, String nickName, String avatarUrl, String userPhone) {
        String secret = Configure.getSecret();
        String appid = Configure.getAppID();
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + code +
                "&grant_type=authorization_code";
        String result = HttpUtils.sendGet(url);
        JSONObject jsonObject = JSONObject.parseObject(result);
        String openid = jsonObject.get("openid").toString();

        ChargeCustomUser userInfo = new ChargeCustomUser();
        userInfo.setCustomName(nickName);
        userInfo.setCustomPhoto(avatarUrl);
        userInfo.setCustomCode(openid);
        userInfo.setCustomPhone(userPhone);
        //会员
        userInfo.setCustomType("1");
        //权限
        userInfo.setDeptId(111L);

        this.addUserInfo(userInfo);

        return AjaxResult.success(new HashMap<String, Object>() {{
            put("openid", openid);
        }});
    }


    @GetMapping("/getSessionKey")
    public AjaxResult getSessionKey(String code) {
        String secret = Configure.getSecret();
        String appid = Configure.getAppID();
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
        String result = HttpUtils.sendGet(url);
        JSONObject jsonObject = JSONObject.parseObject(result);
        String access_token = jsonObject.get("access_token").toString();

        //获取phone
        String url1 = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"
                + "?access_token=" + access_token;
        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.put("code", code);
        String reqJsonStr = JsonUtil.objToString(jsonObject1);
        JSONObject returnInfo = null;
        try {
            returnInfo = JSON.parseObject(HttpClientSslUtils.doPost(url1, reqJsonStr));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return AjaxResult.success(returnInfo);
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param:
     * @Description:小程序获取APPSecret
     * @Return:AjaxResult
     */
    @GetMapping("/getAPPSecret")
    public AjaxResult getAPPSecret() {
        String secret = Configure.getSecret();
        return AjaxResult.success(new HashMap<String, Object>() {{
            put("state", true);
            put("msg", secret);
        }});
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param:
     * @Description:小程序获取手机号后台解析 (暂时废弃 ， 前端获取手机号)
     * @Return:AjaxResult
     */
    @GetMapping("/getPhoneNumber")
    public AjaxResult getPhoneNumber(String encryptedData, String iv, String sessionKey, String openId) {
        if (StringUtils.isEmpty(encryptedData)
                || StringUtils.isEmpty(iv)
                || StringUtils.isEmpty(sessionKey)
                || StringUtils.isEmpty(openId)
        ) {
            return AjaxResult.error("参数错误");
        }
        String decrypt = WXUtils.decrypt(encryptedData, sessionKey, iv);

        if (StringUtils.isEmpty(decrypt)) {
            return AjaxResult.error("解密失败");
        }

        Gson gson = new Gson();
        Map<String, Object> stringList = gson.fromJson(decrypt, new TypeToken<Map<String, Object>>() {
        }.getType());

        return AjaxResult.success(stringList);
    }


    /**
     * (支付宝) 获取用户授权
     *
     * @return
     */
    @GetMapping("/getAlipayInfo")
    public AjaxResult getAlipayInfo(String authCode) throws Exception {
        AlipaySystemOauthTokenResponse response = getAccessToken(authCode);
        if (response.isSuccess()) {
            System.out.println("获取access_token - 调用成功！");
            String accessToken = response.getAccessToken();
            String alipayUserId = response.getUserId();
            AlipayUserInfoShareResponse aliUserInfo = getAliUserInfo(accessToken);
            aliUserInfo.setMobile("18853363925");
            if (aliUserInfo != null) {
                //添加用户信息到信息表
                ChargeCustomUser userInfo = new ChargeCustomUser();
                userInfo.setCustomName(aliUserInfo.getNickName());
                userInfo.setCustomPhoto(aliUserInfo.getAvatar());
                userInfo.setCustomCode(aliUserInfo.getOpenId());
                userInfo.setCustomPhone(aliUserInfo.getMobile());
                //支付宝会员
                userInfo.setCustomType("4");
                //权限
                userInfo.setDeptId(111L);
                this.addUserInfo(userInfo);
                return AjaxResult.success(aliUserInfo);
            }
        }
        System.out.println("获取access_token - 调用失败！");
        return AjaxResult.error("获取access_token - 调用失败！");
    }

    private AlipaySystemOauthTokenResponse getAccessToken(String authCode) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(
                AlipayConfig.getServerUrl(),
                AlipayConfig.getAppId(),
                AlipayConfig.getPrivateKey(),
                AlipayConfig.getFormat(),
                AlipayConfig.getCharset(),
                AlipayConfig.getAlipayPublicKey(),
                AlipayConfig.getSignType());
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(authCode);
        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
        return response;
    }

    // 获取支付宝用户信息
    private AlipayUserInfoShareResponse getAliUserInfo(String accessToken) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient(
                AlipayConfig.getServerUrl(),
                AlipayConfig.getAppId(),
                AlipayConfig.getPrivateKey(),
                AlipayConfig.getFormat(),
                AlipayConfig.getCharset(),
                AlipayConfig.getAlipayPublicKey(),
                AlipayConfig.getSignType());

        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        AlipayUserInfoShareResponse response = alipayClient.execute(request, accessToken);
        if (response.isSuccess()) {
            System.out.println("获取会员信息 - 调用成功");
            return response;
        }
        return null;
    }


    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @Description:小程序获取所有站点信息
     * @Return:AjaxResult
     */
    @GetMapping("/getStationInfo")
    public AjaxResult getStationInfo(String customCode) {

        List<ChargeStation> list = chargeStationMapper.selectChargeStationListAPI(null);

        if (!StringUtils.isEmpty(customCode) && !"null".equals(customCode)) {
            //客户收藏的站点
            List<ChargeStation> collectList = chargeStationMapper.getUserCollectStationList(customCode);

            for (ChargeStation c : list) {
                //站点是否被该客户收藏
                if (collectList.size() > 0) {
                    for (ChargeStation ch : collectList) {
                        if (ch.getChargeStationId().equals(c.getChargeStationId())) {
                            c.setIsCollect("1");
                        }
                    }
                }
            }
        }

        return AjaxResult.success(list);
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @Description:小程序点击标签搜索站点
     * @Return:AjaxResult
     */
    @GetMapping("/getStationListByTag")
    public AjaxResult getStationListByTag(String chargeStationStatus, String customCode, String chargeStationLongitude, String chargeStationLatitude) {
        //全部站点
        List<ChargeStation> list = chargeStationMapper.selectChargeStationListAPI(null);
        List<String> stateList = Arrays.asList(chargeStationStatus.split(","));
        if (stateList.contains("1")) {
            //1.收藏
            if (!StringUtils.isEmpty(customCode) && !"null".equals(customCode)) {
                //客户收藏的站点
                List<ChargeStation> collectList = chargeStationMapper.getUserCollectStationList(customCode);
                if (collectList.size() > 0) {

                    List<Long> idList = new ArrayList<>();
                    for (ChargeStation c : collectList) {
                        idList.add(c.getChargeStationId());
                    }
                    //迭代器删除非收藏站点
                    Iterator<ChargeStation> it = list.iterator();
                    while (it.hasNext()) {
                        ChargeStation next = it.next();
                        if (idList.contains(next.getChargeStationId())) {
                            next.setIsCollect("1");
                        } else {
                            it.remove();
                        }
                    }

                } else {
                    list = new ArrayList<>();
                    return AjaxResult.success(list);
                }
            } else {
                list = new ArrayList<>();
                return AjaxResult.success(list);
            }
        }
        if (stateList.contains("2")) {
            //2.免费停车
            //根据当前时间段获取停车费
            LocalDateTime localDateTime = LocalDateTime.now();
            String timeString = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm"));

            Iterator<ChargeStation> itTwo = list.iterator();
            while (itTwo.hasNext()) {
                ChargeStation next = itTwo.next();
                ChargeStationPrice chargeStationPrice = new ChargeStationPrice(next.getChargeStationCode(), timeString) {
                };
                //查询当前生效策略
                Map<String, Object> stationStopPriceByTactics = chargeStationPriceTacticsMapper.getStationStopPriceByTactics(next.getChargeStationCode());
                if (stationStopPriceByTactics == null) {
                    //查询默认策略
                    stationStopPriceByTactics = chargeStationPriceTacticsMapper.getStationStopPriceByTacticsDefult(next.getChargeStationCode());
                    if (Objects.nonNull(stationStopPriceByTactics)) {
//                        chargeStationPrice.setPriceTypeCode(stationStopPriceByTactics.get("priceTypeCode").toString());
//                        // 查询站点当前时间绑定的策略//查询策略的价格区间  (废弃)
//                        ChargeStationPrice price = chargeStationPriceMapper.selectChargeStationNowPrice(chargeStationPrice);
//                        if (price != null && price.getStopFee() != null) {
//                            if (BigDecimal.ZERO.compareTo(price.getStopFee()) != 0) {
//                                itTwo.remove();
//                            }
//                        } else {
                        //价格区间没有设置停车费，取策略停车费
                        if (stationStopPriceByTactics.get("stopFee") != null
                                && BigDecimal.ZERO.compareTo(new BigDecimal(stationStopPriceByTactics.get("stopFee").toString())) != 0) {
                            itTwo.remove();
                        } else if (stationStopPriceByTactics.get("stopFee") == null) {
                            //策略没有设置停车费
                            itTwo.remove();
                        }
//                        }
                    } else {
                        //没有设置策略
                        itTwo.remove();
                    }
                } else {
//                    chargeStationPrice.setPriceTypeCode(stationStopPriceByTactics.get("priceTypeCode").toString());
//                    ChargeStationPrice price = chargeStationPriceMapper.selectChargeStationNowPrice(chargeStationPrice);
//                    if (price != null && price.getStopFee() != null) {
//                        if (BigDecimal.ZERO.compareTo(price.getStopFee()) != 0) {
//                            itTwo.remove();
//                        }
//                    } else {
//                    }
                    if (stationStopPriceByTactics.get("stopFee") == null) {
                        //策略没有设置停车费
                        itTwo.remove();
                    } else if (stationStopPriceByTactics.get("stopFee") != null
                            && BigDecimal.ZERO.compareTo(new BigDecimal(stationStopPriceByTactics.get("stopFee").toString())) != 0) {
                        //有停车费
                        itTwo.remove();
                    }
                }
            }
            if (list.size() == 0) {
                return AjaxResult.success(list);
            }
        }
        if (stateList.contains("3")) {
            //3.直流快充
            Iterator<ChargeStation> itTwo = list.iterator();
            while (itTwo.hasNext()) {
                ChargeStation next = itTwo.next();
                //查询场站类型 1
                if (!next.getGunType().contains("1")) {
                    itTwo.remove();
                }
            }
            if (list.size() == 0) {
                return AjaxResult.success(list);
            }
        }
        if (stateList.contains("4")) {
            //4.交流快充
            Iterator<ChargeStation> itTwo = list.iterator();
            while (itTwo.hasNext()) {
                ChargeStation next = itTwo.next();
                //查询场站类型 2
                if (!next.getGunType().contains("2")) {
                    itTwo.remove();
                }
            }
            if (list.size() == 0) {
                return AjaxResult.success(list);
            }
        }
        if (stateList.contains("5")) {
            //4.交流慢充
            Iterator<ChargeStation> itTwo = list.iterator();
            while (itTwo.hasNext()) {
                ChargeStation next = itTwo.next();
                //查询场站类型 3
                if (!next.getGunType().contains("3")) {
                    itTwo.remove();
                }
            }
            if (list.size() == 0) {
                return AjaxResult.success(list);
            }
        }

        for (ChargeStation c : list) {
            //站点内 可用设备数量/设备数量
            int dcDeviceNumber = 0;
            int dcDeviceNumberFree = 0;
            //直流快充设备数量(全部)
            Map<String, Object> iotDeviceNumber = chargeStationPileMapper.getIotDeviceNumber(c.getChargeStationCode(), "1");
            if (iotDeviceNumber != null && iotDeviceNumber.get("number") != null) {
                dcDeviceNumber = dcDeviceNumber + Integer.parseInt(iotDeviceNumber.get("number").toString());
            }
            //直流快充设备数量(可用)
            Map<String, Object> iotDeviceNumberFree = chargeStationPileMapper.getIotDeviceNumberFree(c.getChargeStationCode(), "1");
            if (iotDeviceNumberFree != null && iotDeviceNumberFree.get("number") != null) {
                dcDeviceNumberFree = dcDeviceNumberFree + Integer.parseInt(iotDeviceNumberFree.get("number").toString());
            }

            //交流快充设备数量(全部)
            iotDeviceNumber = chargeStationPileMapper.getIotDeviceNumber(c.getChargeStationCode(), "2");
            if (iotDeviceNumber != null && iotDeviceNumber.get("number") != null) {
                dcDeviceNumber = dcDeviceNumber + Integer.parseInt(iotDeviceNumber.get("number").toString());
            }
            //交流快充设备数量(可用)
            iotDeviceNumberFree = chargeStationPileMapper.getIotDeviceNumberFree(c.getChargeStationCode(), "2");
            if (iotDeviceNumberFree != null && iotDeviceNumberFree.get("number") != null) {
                dcDeviceNumberFree = dcDeviceNumberFree + Integer.parseInt(iotDeviceNumberFree.get("number").toString());
            }
            c.setDcDeviceNumber(dcDeviceNumber);
            c.setDcDeviceNumberFree(dcDeviceNumberFree);
            //交流慢充设备数量(全部)
            iotDeviceNumber = chargeStationPileMapper.getIotDeviceNumber(c.getChargeStationCode(), "3");
            if (iotDeviceNumber != null && iotDeviceNumber.get("number") != null) {
                c.setAcDeviceNumber(Integer.parseInt(iotDeviceNumber.get("number").toString()));
            }
            //交流慢充设备数量(可用)
            iotDeviceNumberFree = chargeStationPileMapper.getIotDeviceNumberFree(c.getChargeStationCode(), "2");
            if (iotDeviceNumberFree != null && iotDeviceNumberFree.get("number") != null) {
                c.setAcDeviceNumberFree(Integer.parseInt(iotDeviceNumberFree.get("number").toString()));
            }

            //是否收藏
            chargeStationMapper.getCollectStationByCode(customCode, c.getChargeStationId());

            //计算当前距离
            c.setDistance(getDistance4(new Double(chargeStationLongitude), new Double(chargeStationLatitude),
                    new Double(c.getChargeStationLongitude()), new Double(c.getChargeStationLatitude())));
        }

        list.sort((o1, o2) -> {
            return o1.getDistance().compareTo(o2.getDistance());
        });

        return AjaxResult.success(list);
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @Description:添加客户信息
     * @param: customCode 客户openid
     * @param: customName 客户姓名
     * @param: customPhoto 客户头像
     * @Return:AjaxResult
     */
    @GetMapping("/addUserInfo")
    public AjaxResult addUserInfo(ChargeCustomUser chargeCustomUser) {
        if (StringUtils.isEmpty(chargeCustomUser.getCustomCode())
                || StringUtils.isEmpty(chargeCustomUser.getCustomName())
                || StringUtils.isEmpty(chargeCustomUser.getCustomPhoto())
        ) {
            return AjaxResult.error("参数错误");
        }
        //根据openid验证是否存在该客户
        ChargeCustomUser chargeCustomUsers = chargeCustomUserMapper.selectChargeCustomUserByOpenid(chargeCustomUser.getCustomCode());
        //添加/修改客户
        if (null == chargeCustomUsers) {
            chargeCustomUser.setCreateBy(chargeCustomUser.getCustomName());
            chargeCustomUser.setCreateTime(DateUtils.getNowDate());
            chargeCustomUserMapper.insertChargeCustomUser(chargeCustomUser);
        } else {
            if (chargeCustomUsers.getCustomPhoto().contains("www.sdzctech.cn")) {
                chargeCustomUser.setCustomPhoto(chargeCustomUsers.getCustomPhoto());
            }
            if (!chargeCustomUsers.getCustomName().equals("微信用户") && chargeCustomUser.getCustomName().equals("微信用户")) {
                chargeCustomUser.setCustomName(chargeCustomUsers.getCustomName());
            }
            chargeCustomUser.setCustomId(chargeCustomUsers.getCustomId());
            chargeCustomUser.setUpdateBy(chargeCustomUser.getCustomName());

            chargeCustomUser.setUpdateTime(DateUtils.getNowDate());
            chargeCustomUserMapper.updateChargeCustomUser(chargeCustomUser);
        }


        return AjaxResult.success();
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: customCode 客户openid
     * @Description:小程序获取客户信息
     * @Return:AjaxResult
     */
    @GetMapping("/getUserInfo")
    public AjaxResult getUserInfo(String customCode) {
        if (StringUtils.isEmpty(customCode)) {
            return AjaxResult.error("参数错误");
        }
        //根据客户openid获取客户信息
        ChargeCustomUser chargeCustomUsers = chargeCustomUserMapper.selectChargeCustomUserByOpenid(customCode);
        //红包卡券数量
        chargeCustomUsers.setCardNumber(0);
        return AjaxResult.success(chargeCustomUsers);
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: customCode 客户openid
     * @Description:小程序获取客户收藏的站点
     * @Return:AjaxResult
     */
    @GetMapping("/getUserCollectStationList")
    public AjaxResult getUserCollectStationList(String customCode) {
        if (StringUtils.isEmpty(customCode)) {
            return AjaxResult.error("参数错误");
        }
        //根据客户openid查询客户收藏的站点
        List<ChargeStation> stationList = chargeStationMapper.getUserCollectStationList(customCode);
        return AjaxResult.success(stationList);
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: chargeStationName 关键词
     * @Description:小程序根据关键词获取站点
     * @Return:AjaxResult
     */
    @GetMapping("/getKeywordStationList")
    @ResponseBody
    public AjaxResult getKeywordStationList(ChargeStation chargeStation) {
        //根据关键词获取站点
        List<ChargeStation> stationList = chargeStationMapper.selectChargeStationListAPI(chargeStation);
        //客户收藏的站点
        List<ChargeStation> collectList = new ArrayList<>();
        if (!StringUtils.isEmpty(chargeStation.getCustomCode()) && !"null".equals(chargeStation.getCustomCode())) {
            collectList = chargeStationMapper.getUserCollectStationList(chargeStation.getCustomCode());
        }
        //获取当前时间段
        LocalDateTime localDateTime = LocalDateTime.now();
        String timeString = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm"));

        ChargeStationPrice chargeStationPrice = new ChargeStationPrice();
        chargeStationPrice.setStartTimeString(timeString);
        for (ChargeStation c : stationList) {
            //站点标签
            List<String> tagList = new ArrayList<>();
            //电费信息
            ChargeStationPriceTactics chargeStationPriceTactics = new ChargeStationPriceTactics();
            chargeStationPriceTactics.setStationCode(c.getChargeStationCode());
            chargeStationPriceTactics.setStationId(c.getChargeStationId());
            chargeStationPriceTactics.setIsDefault("0");
            //查询站点绑定的电费策略
            ChargeStationPriceTactics stationNowTactics = chargeStationPriceTacticsService.getStationNowTactics(chargeStationPriceTactics);
            if (Objects.nonNull(stationNowTactics)) {
                chargeStationPrice.setPriceTypeCode(stationNowTactics.getPriceTypeCode());
                chargeStationPrice.setPriceTypeId(stationNowTactics.getPriceTypeId());
                //电费绑定设备
                //查出所有设备下绑定的电费
//                List<ChargeStationPrice> priceList = chargeStationPriceMaspper.selectDevicePriceList(chargeStationPrice);
                SimpleDateFormat sp = new SimpleDateFormat("HH:mm");
                String format = sp.format(new Date());
                SimpleDateFormat spAll = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String formatAll = spAll.format(new Date());
                List<ChargeStationAdjustPrice> priceList = chargeStationAdjustPriceMapper.selectDevicePriceList(chargeStationPrice);
                if (priceList != null && priceList.size() > 0) {
                    isTime:
                    for (ChargeStationAdjustPrice charg : priceList) {
                        try {
                            if ("2".equals(charg.getPricing())) {
                                //判断时间
                                List<ChargeStationAdjustPriceAdditional> tableList = JSONObject.parseArray(charg.getTableData(), ChargeStationAdjustPriceAdditional.class);
                                for (ChargeStationAdjustPriceAdditional additional : tableList) {
                                    String interval = additional.getInterval();
                                    String[] split = interval.split("],");
                                    for (String time : split) {
                                        String timeReplace = time.replace("[", "").replace("]", "").replace("\"", "");
                                        String[] split1 = timeReplace.split(",");

                                        Date startTime = sp.parse(split1[0]);
                                        Date endTime = sp.parse(split1[1]);
                                        Date nowTime = sp.parse(format);
                                        if (startTime.compareTo(nowTime) <= 0 && endTime.compareTo(nowTime) > 0) {
                                            ChargeStationPrice addprice = new ChargeStationPrice();
                                            String device_type = DictUtils.getDictLabel("gun_type", charg.getMold());
                                            addprice.setTerminalType(device_type);
                                            addprice.setStartTime(spAll.parse(formatAll.substring(0, 11) + split1[0] + ":00"));
                                            addprice.setEndTime(spAll.parse(formatAll.substring(0, 11) + split1[1] + ":00"));
                                            addprice.setElectricCharge(new BigDecimal(String.valueOf(additional.getElectricityPrice())));
                                            addprice.setOriginalPrice(new BigDecimal(String.valueOf(additional.getElectricityPrice())).add(new BigDecimal("0.5")));
                                            addprice.setServiceFee(new BigDecimal(String.valueOf(additional.getServiceCharge())));
                                            c.setElectricCharge(new BigDecimal(String.valueOf(additional.getElectricityPrice())));
                                            c.setOriginalPrice(new BigDecimal(String.valueOf(additional.getElectricityPrice())).add(new BigDecimal("0.5")));
                                            c.setServiceFee(new BigDecimal(String.valueOf(additional.getServiceCharge())));
                                            //策略停车费
                                            if (!StringUtils.isEmpty(stationNowTactics.getStopFee())) {
                                                c.setStopFee(new BigDecimal(stationNowTactics.getStopFee()));
                                                addprice.setStopFee(new BigDecimal(stationNowTactics.getStopFee()));
                                                if (new BigDecimal(stationNowTactics.getStopFee()).compareTo(BigDecimal.ZERO) == 0 && !tagList.contains("免费停车")) {
                                                    tagList.add("免费停车");
                                                }
                                            }
                                            c.setStartTime(split1[0]);
                                            c.setEndTime(split1[1]);
                                            c.setPriceList(new ArrayList<ChargeStationPrice>() {{
                                                add(addprice);
                                            }});
                                            break isTime;
                                        }
                                    }
                                }
                            } else {
                                ChargeStationPrice addprice = new ChargeStationPrice();
                                String device_type = DictUtils.getDictLabel("gun_type", charg.getMold());
                                addprice.setTerminalType(device_type);
                                addprice.setStartTime(spAll.parse(formatAll.substring(0, 11) + "00:00:00"));
                                addprice.setEndTime(spAll.parse(formatAll.substring(0, 11) + "23:59:59"));
                                addprice.setElectricCharge(new BigDecimal(String.valueOf(charg.getElectricPrice())));
                                addprice.setOriginalPrice(new BigDecimal(String.valueOf(charg.getElectricPrice())).add(new BigDecimal("0.5")));
                                addprice.setServiceFee(new BigDecimal(String.valueOf(charg.getServicePrice())));
                                c.setElectricCharge(new BigDecimal(String.valueOf(charg.getElectricPrice())));
                                c.setOriginalPrice(new BigDecimal(String.valueOf(charg.getElectricPrice())).add(new BigDecimal("0.5")));
                                c.setServiceFee(new BigDecimal(String.valueOf(charg.getServicePrice())));
                                //策略停车费
                                if (!StringUtils.isEmpty(stationNowTactics.getStopFee())) {
                                    c.setStopFee(new BigDecimal(stationNowTactics.getStopFee()));
                                    addprice.setStopFee(new BigDecimal(stationNowTactics.getStopFee()));
                                    if (new BigDecimal(stationNowTactics.getStopFee()).compareTo(BigDecimal.ZERO) == 0 && !tagList.contains("免费停车")) {
                                        tagList.add("免费停车");
                                    }
                                }
                                c.setStartTime("00:00");
                                c.setEndTime("23:59");
                                c.setPriceList(new ArrayList<ChargeStationPrice>() {{
                                    add(addprice);
                                }});
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                } else {
                    c.setElectricCharge(new BigDecimal(0.00));
                    c.setOriginalPrice(new BigDecimal(0.00));
                    c.setServiceFee(new BigDecimal(0.00));
                    c.setStopFee(new BigDecimal(0.00));
                    c.setStartTime("");
                    c.setEndTime("");
                }
                if (!StringUtils.isEmpty(c.getChargeStationCurrentType())) {
                    //站点类型
                    String device_type = DictUtils.getDictLabel("current_type", c.getChargeStationCurrentType());
                    c.setChargeStationCurrentType(device_type);
                } else {
                    c.setChargeStationCurrentType("");
                }
                //场站电流类型
                if (c.getGunType().contains("1") && !tagList.contains("直流快充")) {
                    tagList.add("直流快充");
                }
                if (c.getGunType().contains("2") && !tagList.contains("交流快充")) {
                    tagList.add("交流快充");
                }
                if (c.getGunType().contains("3") && !tagList.contains("交流慢充")) {
                    tagList.add("交流慢充");
                }
                //站点内 可用设备数量/设备数量
                int dcDeviceNumber = 0;
                int dcDeviceNumberFree = 0;
                //直流快充设备数量(全部)
                Map<String, Object> iotDeviceNumber = chargeStationPileMapper.getIotDeviceNumber(c.getChargeStationCode(), "1");
                if (iotDeviceNumber != null && iotDeviceNumber.get("number") != null) {
                    dcDeviceNumber = dcDeviceNumber + Integer.parseInt(iotDeviceNumber.get("number").toString());
                    //  c.setDcDeviceNumber(Integer.parseInt(iotDeviceNumber.get("number").toString()));
                    if (Integer.parseInt(iotDeviceNumber.get("number").toString()) > 0
                            && !tagList.contains("直流快充")) {
                        tagList.add("直流快充");
                    }
                }
                //直流快充设备数量(可用)
                Map<String, Object> iotDeviceNumberFree = chargeStationPileMapper.getIotDeviceNumberFree(c.getChargeStationCode(), "1");
                if (iotDeviceNumberFree != null && iotDeviceNumberFree.get("number") != null) {
                    dcDeviceNumberFree = dcDeviceNumberFree + Integer.parseInt(iotDeviceNumberFree.get("number").toString());
                }

                //交流快充设备数量(全部)
                iotDeviceNumber = chargeStationPileMapper.getIotDeviceNumber(c.getChargeStationCode(), "2");
                if (iotDeviceNumber != null && iotDeviceNumber.get("number") != null) {
                    dcDeviceNumber = dcDeviceNumber + Integer.parseInt(iotDeviceNumber.get("number").toString());
                    if (Integer.parseInt(iotDeviceNumber.get("number").toString()) > 0
                            && !tagList.contains("交流快充")) {
                        tagList.add("交流快充");
                    }
                }
                //交流快充设备数量(可用)
                iotDeviceNumberFree = chargeStationPileMapper.getIotDeviceNumberFree(c.getChargeStationCode(), "2");
                if (iotDeviceNumberFree != null && iotDeviceNumberFree.get("number") != null) {
                    dcDeviceNumberFree = dcDeviceNumberFree + Integer.parseInt(iotDeviceNumberFree.get("number").toString());
                }
                c.setDcDeviceNumber(dcDeviceNumber);
                c.setDcDeviceNumberFree(dcDeviceNumberFree);
                //交流慢充设备数量(全部)
                iotDeviceNumber = chargeStationPileMapper.getIotDeviceNumber(c.getChargeStationCode(), "3");
                if (iotDeviceNumber != null && iotDeviceNumber.get("number") != null) {
                    c.setAcDeviceNumber(Integer.parseInt(iotDeviceNumber.get("number").toString()));
                    if (Integer.parseInt(iotDeviceNumber.get("number").toString()) > 0
                            && !tagList.contains("交流慢充")) {
                        tagList.add("交流慢充");
                    }
                }
                //交流慢充设备数量(可用)
                iotDeviceNumberFree = chargeStationPileMapper.getIotDeviceNumberFree(c.getChargeStationCode(), "2");
                if (iotDeviceNumberFree != null && iotDeviceNumberFree.get("number") != null) {
                    c.setAcDeviceNumberFree(Integer.parseInt(iotDeviceNumberFree.get("number").toString()));
                }

                //站点是否被该客户收藏
                if (collectList.size() > 0) {
                    for (ChargeStation ch : collectList) {
                        if (ch.getChargeStationId().equals(c.getChargeStationId())) {
                            c.setIsCollect("1");
                        }
                    }
                }

                c.setTagList(tagList);

                //计算当前距离
                if (chargeStation.getChargeStationLongitude() != null && chargeStation.getChargeStationLatitude() != null
                        && c.getChargeStationLongitude() != null && c.getChargeStationLongitude() != null) {
                    c.setDistance(getDistance4(new Double(chargeStation.getChargeStationLongitude())
                            , new Double(chargeStation.getChargeStationLatitude()), new Double(c.getChargeStationLongitude()),
                            new Double(c.getChargeStationLatitude())));
                } else {
                    c.setDistance(BigDecimal.ZERO);
                }

            }
        }

        stationList.sort((o1, o2) -> {
            if (o1.getDistance() != null && o2.getDistance() != null) {
                return o1.getDistance().compareTo(o2.getDistance());
            } else {
                return o1.getChargeStationId().compareTo(o2.getChargeStationId());
            }
        });

        return AjaxResult.success(stationList);
    }


    /**
     * 高德地图计算方法
     *
     * @param longitude1 第一点的经度
     * @param latitude1  第一点的纬度
     * @param longitude2 第二点的经度
     * @param latitude2  第二点的纬度
     * @return 返回的距离，单位m
     */
    public static BigDecimal getDistance4(double longitude1, double latitude1, double longitude2, double latitude2) {
        if (longitude1 == 0 || latitude1 == 0 || latitude2 == 0 || longitude2 == 0) {
            return new BigDecimal("-1.0");
        }
        longitude1 *= 0.01745329251994329;
        latitude1 *= 0.01745329251994329;
        longitude2 *= 0.01745329251994329;
        latitude2 *= 0.01745329251994329;
        double var1 = Math.sin(longitude1);
        double var2 = Math.sin(latitude1);
        double var3 = Math.cos(longitude1);
        double var4 = Math.cos(latitude1);
        double var5 = Math.sin(longitude2);
        double var6 = Math.sin(latitude2);
        double var7 = Math.cos(longitude2);
        double var8 = Math.cos(latitude2);
        double[] var10 = new double[3];
        double[] var20 = new double[3];
        var10[0] = var4 * var3;
        var10[1] = var4 * var1;
        var10[2] = var2;
        var20[0] = var8 * var7;
        var20[1] = var8 * var5;
        var20[2] = var6;

        Double distance = Math.asin(Math.sqrt((var10[0] - var20[0]) * (var10[0] - var20[0]) + (var10[1] - var20[1]) * (var10[1] - var20[1]) + (var10[2] - var20[2]) * (var10[2] - var20[2])) / 2.0) * 1.27420015798544E7;
        // 结果四舍五入 保留2位小数
        return new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: chargeStation
     * @Description:小程序获取站点全天充电电价 (暂时废弃)
     * @Return:AjaxResult
     */
    @GetMapping("/getStationPriceList")
    public AjaxResult getStationPriceList(ChargeStationPrice chargeStationPrice) {
        List<Map<String, Object>> list = chargeStationPriceMapper.getStationPriceList(chargeStationPrice);
        return AjaxResult.success(list);
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: customCode 客户openid
     * @param: chargeStationId 站点Id
     * @Description:小程序客户收藏站点
     * @Return:AjaxResult
     */
    @GetMapping("/toCollectStation")
    public AjaxResult toCollectStation(CustomChargeStation customChargeStation) {
        if (StringUtils.isEmpty(customChargeStation.getChargeStationId())
                || StringUtils.isEmpty(customChargeStation.getCustomCode())) {
            return AjaxResult.error("参数错误");
        }
        customChargeStation.setCreateName(customChargeStation.getCreateName());
        customChargeStation.setCreateTime(DateUtils.getNowDate());
        boolean b = chargeStationMapper.inserCollectStation(customChargeStation);
        if (b) {
            return AjaxResult.success("收藏成功");
        } else {
            return AjaxResult.error("收藏失败");
        }
    }


    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: customCode 客户openid
     * @param: chargeStationId 站点Id
     * @Description:小程序客户收藏站点
     * @Return:AjaxResult
     */
    @GetMapping("/toDisCollectStation")
    public AjaxResult toDisCollectStation(CustomChargeStation customChargeStation) {
        if (StringUtils.isEmpty(customChargeStation.getChargeStationId())
                || StringUtils.isEmpty(customChargeStation.getCustomCode())) {
            return AjaxResult.error("参数错误");
        }
        boolean b = chargeStationMapper.delCollectStation(customChargeStation);
        if (b) {
            return AjaxResult.success("取消成功");
        } else {
            return AjaxResult.error("取消失败");
        }
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: customCode 客户openid
     * @param: chargeStationId 站点Id
     * @Description:小程序查询站点所有设备终端
     * @Return:AjaxResult
     */
    @GetMapping("/getDeviceList")
    public AjaxResult getDeviceList(IotDeviceAssociation iotDeviceAssociation) {
        if (null == iotDeviceAssociation.getStationId() || null == iotDeviceAssociation.getStationCode()) {
            return AjaxResult.error("参数错误");
        }
        ChargeStationPriceTactics chargeStationPriceTactics = new ChargeStationPriceTactics();
        chargeStationPriceTactics.setStationCode(iotDeviceAssociation.getStationCode());
        chargeStationPriceTactics.setStationId(iotDeviceAssociation.getStationId());
        chargeStationPriceTactics.setIsDefault("0");
        ChargeStationPriceTactics stationNowTactics = chargeStationPriceTacticsService.getStationNowTactics(chargeStationPriceTactics);
        if (Objects.isNull(stationNowTactics)) {
            return AjaxResult.error("未配置策略");
        } else {
            iotDeviceAssociation.setPriceTypeCode(stationNowTactics.getPriceTypeCode());
            List<IotDeviceAssociation> iotDeviceSubsidiaries = chargeStationPileMapper.getDeviceList(iotDeviceAssociation);
            for (IotDeviceAssociation i : iotDeviceSubsidiaries) {
                ChargeStationPort chargeStationPort = new ChargeStationPort();
                chargeStationPort.setDeviceId(i.getDeviceId());
//                List<ChargeStationPort> list = chargeStationPortService.getList(chargeStationPort);
                //枪口
                List<ChargeStationPort> list = chargeStationPortMapper.selectPortList(chargeStationPort);
                i.setChargeStationPortList(list);
//                //获取设备价格列表
//                ChargeStationPrice chargeStationPrice = new ChargeStationPrice();
//                chargeStationPrice.setPriceTypeCode(i.getPriceTypeCode());
//                List<Map<String, Object>> stationPriceList = chargeStationPriceMapper.getStationPriceList(chargeStationPrice);
//                //设备电流类型
//                String device_type = DictUtils.getDictLabel("gun_type", i.getTerminalType());
//                for (Map map : stationPriceList) {
//                    map.put("terminalType", device_type);
//                }
//                i.setPriceList(stationPriceList);
            }
            return AjaxResult.success(iotDeviceSubsidiaries);
        }
    }

    /**
     * @Author:gaojikun
     * @Date:2023-05-18 16:51
     * @param: customCode 客户openid
     * @param: chargeStationId 站点Id
     * @Description:小程序扫码跳转设备详情查询设备详情
     * @Return:AjaxResult
     */
    @GetMapping("/queryDeviceInfo")
    public AjaxResult queryDeviceInfo(IotDeviceAssociation iotDeviceAssociation) {
        if (null == iotDeviceAssociation.getStationId() || null == iotDeviceAssociation.getStationCode() || null == iotDeviceAssociation.getDeviceId()) {
            return AjaxResult.error("参数错误");
        }
        ChargeStationPriceTactics chargeStationPriceTactics = new ChargeStationPriceTactics();
        chargeStationPriceTactics.setStationCode(iotDeviceAssociation.getStationCode());
        chargeStationPriceTactics.setStationId(iotDeviceAssociation.getStationId());
        chargeStationPriceTactics.setIsDefault("0");
        ChargeStationPriceTactics stationNowTactics = chargeStationPriceTacticsService.getStationNowTactics(chargeStationPriceTactics);
        if (Objects.isNull(stationNowTactics)) {
            return AjaxResult.error("未配置策略");
        } else {
            iotDeviceAssociation.setPriceTypeCode(stationNowTactics.getPriceTypeCode());
            IotDeviceAssociation deviceInfo = chargeStationPileMapper.getDeviceInfo(iotDeviceAssociation);

            ChargeStationPort chargeStationPort = new ChargeStationPort();
            chargeStationPort.setDeviceId(deviceInfo.getDeviceId());
            //查询枪口数据库
//            List<ChargeStationPort> list = chargeStationPortService.getList(chargeStationPort);
            List<ChargeStationPort> list = chargeStationPortMapper.selectPortList(chargeStationPort);
            for (ChargeStationPort stationPort : list) {
                Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(stationPort.getId());
                if (realData.containsKey("ifInsertGun") && realData.containsKey("runningState")) {
                    String portStatus = String.valueOf(realData.get("ifInsertGun").getValue());
                    String runningState = String.valueOf(realData.get("runningState").getValue());
                    if ("1".equals(portStatus) && "2".equals(runningState)) {
                        //空闲已插枪算插枪
                        stationPort.setServiceStatus("4");
                    }
                }
            }

            deviceInfo.setChargeStationPortList(list);
            //获取设备价格列表
            SimpleDateFormat sp = new SimpleDateFormat("HH:mm");
            String format = sp.format(new Date());
            ChargeStationPrice chargeStationPrice = new ChargeStationPrice();
            chargeStationPrice.setPriceTypeId(stationNowTactics.getPriceTypeId());
            List<ChargeStationAdjustPrice> priceList = chargeStationAdjustPriceMapper.selectDevicePriceList(chargeStationPrice);
            if (priceList != null && priceList.size() > 0) {
                isTime:
                for (ChargeStationAdjustPrice charg : priceList) {
                    if ("2".equals(charg.getPricing())) {
                        //价格详情 -》电价调整所有信息
                        List<ChargeStationAdjustPriceAdditional> tableList = JSONObject.parseArray(charg.getTableData(), ChargeStationAdjustPriceAdditional.class);
                        for (ChargeStationAdjustPriceAdditional additional : tableList) {
                            additional.setOriginalPrice(new BigDecimal(String.valueOf(additional.getElectricityPrice())).add(new BigDecimal("0.5")).doubleValue());
                            additional.setNowPrice(new BigDecimal(String.valueOf(additional.getElectricityPrice())).add(new BigDecimal(additional.getServiceCharge())).setScale(2, RoundingMode.HALF_UP).doubleValue());
                            String device_type = DictUtils.getDictLabel("gun_type", charg.getMold());
                            additional.setTerminalType(device_type);
                        }
                        deviceInfo.setPriceList(tableList);
                        //判断时间
                        for (ChargeStationAdjustPriceAdditional additional : tableList) {
                            String interval = additional.getInterval();
                            String[] split = interval.split("],");
                            for (String time : split) {
                                String timeReplace = time.replace("[", "").replace("]", "").replace("\"", "");
                                String[] split1 = timeReplace.split(",");
                                try {
                                    Date startTime = sp.parse(split1[0]);
                                    Date endTime = sp.parse(split1[1]);
                                    Date nowTime = sp.parse(format);
                                    if (startTime.compareTo(nowTime) < 0 && endTime.compareTo(nowTime) > 0) {
                                        deviceInfo.setElectricCharge(new BigDecimal(String.valueOf(additional.getElectricityPrice())).add(new BigDecimal(String.valueOf(additional.getServiceCharge()))));
                                        deviceInfo.setServiceFee(new BigDecimal(String.valueOf(additional.getServiceCharge())));
                                        deviceInfo.setStartTime(split1[0]);
                                        deviceInfo.setEndTime(split1[1]);
                                        break isTime;
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }

                            }
                        }
                    } else {
                        deviceInfo.setElectricCharge(new BigDecimal(String.valueOf(charg.getElectricPrice())).add(new BigDecimal(String.valueOf(charg.getServicePrice()))));
                        deviceInfo.setServiceFee(new BigDecimal(String.valueOf(charg.getServicePrice())));
                        deviceInfo.setStartTime("00:00");
                        deviceInfo.setEndTime("23:59");
                        //价格详情
                        ChargeStationAdjustPriceAdditional priceInfo = new ChargeStationAdjustPriceAdditional();
                        String device_type = DictUtils.getDictLabel("gun_type", charg.getMold());
                        priceInfo.setTerminalType(device_type);
                        priceInfo.setOriginalPrice(new BigDecimal(charg.getElectricPrice()).add(new BigDecimal(charg.getServicePrice())).doubleValue());
                        priceInfo.setNowPrice(new BigDecimal(String.valueOf(charg.getElectricPrice())).add(new BigDecimal(String.valueOf(charg.getServicePrice()))).doubleValue());
                        priceInfo.setElectricityPrice(new BigDecimal(charg.getElectricPrice()).doubleValue());
                        priceInfo.setServiceCharge(new BigDecimal(charg.getServicePrice()).doubleValue());

                        deviceInfo.setPriceList(new ArrayList<ChargeStationAdjustPriceAdditional>() {{
                            add(priceInfo);
                        }});
                    }
                }
            }
//            //获取设备价格列表
//            ChargeStationPrice chargeStationPrice = new ChargeStationPrice();
//            chargeStationPrice.setPriceTypeCode(deviceInfo.getPriceTypeCode());
//            List<Map<String, Object>> stationPriceList = chargeStationPriceMapper.getStationPriceList(chargeStationPrice);
//            //设备电流类型
//            String device_type = DictUtils.getDictLabel("gun_type", deviceInfo.getTerminalType());
//
//
//            for (Map map : stationPriceList) {
//                map.put("terminalType", device_type);
//            }
//            deviceInfo.setPriceList(stationPriceList);

            return AjaxResult.success(deviceInfo);
        }
    }

    //获取枪口状态
    @GetMapping("/putPortInfo")
    public AjaxResult putPortInfo(String deviceId) {
        ChargeStationPort chargeStationPort = new ChargeStationPort();
        chargeStationPort.setDeviceId(deviceId);
        List<ChargeStationPort> portTagList = chargeStationPortMapper.selectPortList(chargeStationPort);
        for (ChargeStationPort port : portTagList) {
            remoteInstructSendService.getRealData(deviceId, port.getId().substring(port.getId().length() - 2), "YTSN-CDZ-N01");
        }

        return AjaxResult.success(portTagList);
    }

    //查询枪口状态
    @GetMapping("/queryPortInfo")
    public AjaxResult queryPortInfo(String deviceId) {
        ChargeStationPort chargeStationPort = new ChargeStationPort();
        chargeStationPort.setDeviceId(deviceId);
        List<ChargeStationPort> portTagList = chargeStationPortMapper.selectPortList(chargeStationPort);
        for (ChargeStationPort port : portTagList) {
            Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(port.getId());
            if (realData.containsKey("ifInsertGun") && realData.containsKey("runningState")) {
                String portStatus = String.valueOf(realData.get("ifInsertGun").getValue());
                String runningState = String.valueOf(realData.get("runningState").getValue());
                if ("1".equals(portStatus) && "2".equals(runningState)) {
                    //空闲已插枪算插枪
                    port.setServiceStatus("4");
                }
            }
        }

        return AjaxResult.success(portTagList);
    }


    public IotDeviceSubsidiary getIotDeviceList(IotDeviceSubsidiary iotDeviceSubsidiary) {
        IotDevice iotDevice = new IotDevice();
        iotDevice.setId(iotDeviceSubsidiary.getDeviceId());
        List<IotDevice> iotDevices = iotDeviceService.listDevice(iotDevice);
        //测试暂时注掉
        for (IotDevice IotDevice : iotDevices) {
            Object numberValue = 0;
            //获取枪的状态
            List<Sort> sortsList = new ArrayList();
            Sort sort = new Sort();
            sort.setOrder("desc");
            sort.setName("timestamp");
            QueryParamEntity queryParams = new QueryParamEntity();
            queryParams.setPageIndex(0);
            queryParams.setPageSize(1);
            queryParams.setSorts(sortsList);
            Mono<PagerResult<DeviceProperty>> pagerResultMono = deviceDataService.queryPropertyPage(iotDeviceSubsidiary.getDeviceId(),
                    "spearWorkStatus" + IotDevice.getId().substring(IotDevice.getId().length() - 1),
                    queryParams);
            List<DeviceProperty> data = pagerResultMono.block().getData();
            if (data.size() > 0) {
                //枪的状态
                numberValue = data.get(0).getNumberValue();
            }
            IotDevice.setDeviceState(numberValue.toString());
        }

        List<IotDevice> iotDeviceList = new ArrayList<>();
        if (iotDevices.size() > 0) {
            for (int i = 0; i < 2; i++) {
                IotDevice iotDevice1 = iotDevices.get(0);
                if (i == 0) {
                    iotDevice1.setDeviceState(null);
                } else {
                    iotDevice1.setDeviceState(String.valueOf(1));
                }
                iotDeviceList.add(iotDevice1);
            }
        }
        iotDeviceSubsidiary.setPortList(iotDeviceList);
        return iotDeviceSubsidiary;
    }

    /**
     * @Author:gaojikun
     * @Description:小程序添加客户车辆
     * @Return:AjaxResult
     */
    @GetMapping("/updateCustCar")
    public AjaxResult updateCustCar(ChargeCar chargeCar) {
        if (StringUtils.isEmpty(chargeCar.getCustomCode())
                || StringUtils.isEmpty(chargeCar.getBrand())
                || StringUtils.isEmpty(chargeCar.getCarNo())
                || StringUtils.isEmpty(chargeCar.getCarImage())) {
            return AjaxResult.error("参数错误");
        }
        //车牌号查重
        List<ChargeCar> checkCars = chargeCarMapper.checkChargeCar(chargeCar);
        if (null != checkCars && checkCars.size() > 0) {
            return AjaxResult.error("车牌号重复!");
        } else {
            int i = 0;
            //添加/修改车辆
            if (null == chargeCar.getCarId()) {
                i = chargeCarMapper.insertChargeCar(chargeCar);
            } else {
                i = chargeCarMapper.updateChargeCar(chargeCar);
            }
            if (i != 1) {
                return AjaxResult.error("编辑信息失败");
            }
        }

        return AjaxResult.success("编辑车辆信息成功");
    }


    /**
     * @Author:gaojikun
     * @Description:小程序删除客户车辆
     * @Return:AjaxResult
     */
    @GetMapping("/deleteCustCar")
    public AjaxResult deleteCustCar(ChargeCar chargeCar) {
        if (StringUtils.isEmpty(chargeCar.getCustomCode())
                || StringUtils.isEmpty(chargeCar.getCarNo())) {
            return AjaxResult.error("参数错误");
        }
        boolean b = chargeCarMapper.deleteChargeCarByCode(chargeCar);
        if (b) {
            return AjaxResult.success("删除成功");
        } else {
            return AjaxResult.error("删除失败");
        }
    }


    /**
     * @Author:gaojikun
     * @Description:小程序查询客户车辆列表
     * @Return:AjaxResult
     */
    @GetMapping("/queryCustCar")
    public AjaxResult queryCustCar(ChargeCar chargeCar) {
        if (StringUtils.isEmpty(chargeCar.getCustomCode())) {
            return AjaxResult.error("参数错误");
        }

        List<ChargeCar> chargeCars = chargeCarMapper.selectChargeCarByCustomCode(chargeCar);
        return AjaxResult.success(chargeCars);
    }


    /**
     * @Author:gaojikun
     * @Description:小程序查询订单列表
     * @Return:AjaxResult
     */
    @GetMapping("/getChargingRecordList")
    public AjaxResult getChargingRecordList(ChargeCustomOrderInfo chargeCustomOrderInfo) {
        if (StringUtils.isEmpty(chargeCustomOrderInfo.getCustomCode())) {
            return AjaxResult.error("参数错误");
        }
        //所有充电订单
        List<Map<String, Object>> lists = chargeCustomOrderInfoMapper.getChargingRecordList(chargeCustomOrderInfo);
        for (Map map : lists) {
//            if (null != map.get("chargingTime") && !StringUtils.isEmpty(map.get("chargingTime").toString())) {
//                String chargingTime = getVideoFormat(Long.parseLong(map.get("chargingTime").toString()));
//                map.put("chargingTime", chargingTime);
//            }
            //交易流水号
            if (map.get("orderStatus") != null && "1".equals(map.get("orderStatus").toString())) {
                ChargePileOrderInfo chargePileOrderInfoByCode = new ChargePileOrderInfo();
                chargePileOrderInfoByCode.setOrderCode(map.get("orderCode").toString());
                chargePileOrderInfoByCode = chargeCustomOrderInfoMapper.getChargePileOrderInfoByCode(chargePileOrderInfoByCode);
                map.put("transactionNum", chargePileOrderInfoByCode.getTransactionNum());
            }
            //评价
            ChargeCustomOrderEvaluation chargeCustomOrderEvaluation = new ChargeCustomOrderEvaluation();
            chargeCustomOrderEvaluation.setOrderCode(map.get("orderCode").toString());
            List<ChargeCustomOrderEvaluation> chargeCustomOrderEvaluations = chargeCustomOrderEvaluationMapper.selectChargeCustomOrderEvaluationList(chargeCustomOrderEvaluation);
            if (chargeCustomOrderEvaluations != null && chargeCustomOrderEvaluations.size() > 0) {
                map.put("evaluationState", "1");
            } else {
                map.put("evaluationState", "0");
            }
            //发票
            ChargeCustomOrderInvoice chargeCustomOrderInvoice = new ChargeCustomOrderInvoice();
            chargeCustomOrderInvoice.setOrderCode(map.get("orderCode").toString());
            List<ChargeCustomOrderInvoice> chargeCustomOrderInvoices = chargeCustomOrderInvoiceMapper.selectChargeCustomOrderInvoiceList(chargeCustomOrderInvoice);
            if (chargeCustomOrderInvoices != null && chargeCustomOrderInvoices.size() > 0) {
                map.put("invoiceState", "1");
            } else {
                map.put("invoiceState", "0");
            }
            //故障
            ChargeFault chargeFault = new ChargeFault();
            chargeFault.setOrderInfoCode(map.get("orderCode").toString());
            List<ChargeFault> chargeFaults = chargeFaultMapper.selectChargeFaultList(chargeFault);
            if (chargeFaults != null && chargeFaults.size() > 0) {
                map.put("faultState", chargeFaults.get(0).getDeviceFaultId());
            } else {
                map.put("faultState", "0");
            }

        }

        return AjaxResult.success(lists);
    }

    @GetMapping("/getChargingRecordDetails")
    public AjaxResult getChargingRecordDetails(String transactionNum) {
        Map<String, Object> details = chargeCustomOrderInfoMapper.getChargingRecordDetails(transactionNum);
        details.put("transactionNum", transactionNum);
        details.put("evaluationState", "0");
        details.put("invoiceState", "0");
        return AjaxResult.success(details);
    }

    /**
     * 将秒数转化为时分秒格式
     */
    public static String getVideoFormat(long time) {
        int temp = (int) time;
        int hh = temp / 3600;
        int mm = (temp % 3600) / 60;
        int ss = (temp % 3600) % 60;
        return (hh < 10 ? ("0" + hh) : hh) + ":" +
                (mm < 10 ? ("0" + mm) : mm) + ":" +
                (ss < 10 ? ("0" + ss) : ss);
    }

    /**
     * @Author:gaojikun
     * @Description:小程序申请发票
     * @Return:AjaxResult
     */
    @GetMapping("/insertInvoiceApplication")
    public AjaxResult insertInvoiceApplication(ChargeCustomOrderInvoice chargeCustomOrderInvoice) {
        if (StringUtils.isEmpty(chargeCustomOrderInvoice.getCustomCode())
                || StringUtils.isEmpty(chargeCustomOrderInvoice.getInvoiceEmail())
                || StringUtils.isEmpty(chargeCustomOrderInvoice.getInvoiceDutyParagraph())
                || StringUtils.isEmpty(chargeCustomOrderInvoice.getInvoiceHeaderType())
                || StringUtils.isEmpty(chargeCustomOrderInvoice.getInvoiceHeader())
                || StringUtils.isEmpty(chargeCustomOrderInvoice.getInvoiceType())
                || StringUtils.isEmpty(chargeCustomOrderInvoice.getOrderCode())
                || null == chargeCustomOrderInvoice.getChargingFee()
        ) {
            return AjaxResult.error("参数错误");
        }

        //发票查重
        List<ChargeCustomOrderInvoice> invoices = chargeCustomOrderInvoiceMapper.selectChargeCustomOrderInvoiceList(chargeCustomOrderInvoice);
        if (null != invoices && invoices.size() > 0) {
            return AjaxResult.error("已经申请发票，请等待审核");
        }

        //添加发票
        chargeCustomOrderInvoice.setCreateTime(DateUtils.getNowDate());
        boolean isAdd = chargeCustomOrderInvoiceMapper.insertChargeCustomOrderInvoice(chargeCustomOrderInvoice);

        if (isAdd) {
            return AjaxResult.success("申请成功");
        } else {
            return AjaxResult.error("申请失败");
        }
    }

    /**
     * @Author:gaojikun
     * @Description:小程序发表评价
     * @Return:AjaxResult
     */
    @GetMapping("/insertOrderEvaluation")
    public AjaxResult insertOrderEvaluation(ChargeCustomOrderEvaluation chargeCustomOrderEvaluation) {
        if (StringUtils.isEmpty(chargeCustomOrderEvaluation.getCustomCode())
                || StringUtils.isEmpty(chargeCustomOrderEvaluation.getOrderCode())
                || StringUtils.isEmpty(chargeCustomOrderEvaluation.getEvaluation())
                || StringUtils.isEmpty(chargeCustomOrderEvaluation.getSatisfied())
        ) {
            return AjaxResult.error("参数错误");
        }

        //是否已评价
        List<ChargeCustomOrderEvaluation> evaluations = chargeCustomOrderEvaluationMapper.selectChargeCustomOrderEvaluationList(chargeCustomOrderEvaluation);
        if (null != evaluations && evaluations.size() > 0) {
            return AjaxResult.error("已评价");
        }

        //添加评价
        chargeCustomOrderEvaluation.setCreateTime(DateUtils.getNowDate());
        boolean isAdd = chargeCustomOrderEvaluationMapper.insertChargeCustomOrderEvaluation(chargeCustomOrderEvaluation);

        if (isAdd) {
            return AjaxResult.success("评价成功");
        } else {
            return AjaxResult.error("评价失败");
        }
    }

    /**
     * @Author:gaojikun
     * @Description:小程序用户评价列表
     * @Return:AjaxResult
     */
    @GetMapping("/getDeviceEvaluation")
    public AjaxResult getDeviceEvaluation(ChargeCustomOrderEvaluation chargeCustomOrderEvaluation) {
        if (StringUtils.isEmpty(chargeCustomOrderEvaluation.getStationId())) {
            return AjaxResult.error("参数错误");
        }

        List<ChargeCustomOrderEvaluation> evaluations = chargeCustomOrderEvaluationMapper.selectChargeCustomOrderEvaluationList(chargeCustomOrderEvaluation);
        return AjaxResult.success(evaluations);
    }

    /**
     * @Author:gaojikun
     * @Description:小程序用户反馈
     * @Return:AjaxResult
     */
    @GetMapping("/insertFeedbook")
    public AjaxResult insertFeedbook(ChargeFeedbook chargeFeedbook) {
        if (StringUtils.isEmpty(chargeFeedbook.getCustomCode())
                || StringUtils.isEmpty(chargeFeedbook.getFeedBook())
        ) {
            return AjaxResult.error("参数错误");
        }

        chargeFeedbook.setCreateTime(DateUtils.getNowDate());
        boolean isAdd = chargeCustomOrderEvaluationMapper.insertFeedbook(chargeFeedbook);
        if (isAdd) {
            return AjaxResult.success("提交成功");
        } else {
            return AjaxResult.error("提交失败");
        }
    }

    /**
     * @Author:gaojikun
     * @Description: 设备是否插枪
     * @Return:AjaxResult
     */
    @GetMapping("/queryGunState")
    public AjaxResult queryGunState(IotDeviceSubsidiary iotDeviceSubsidiary) {
        if (StringUtils.isEmpty(iotDeviceSubsidiary.getDeviceId()) || StringUtils.isEmpty(iotDeviceSubsidiary.getChoosePortId())) {
            return AjaxResult.error("参数错误");
        }
        Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(iotDeviceSubsidiary.getChoosePortId());
        if (realData.containsKey("ifInsertGun")) {
            String ifInsertGun = String.valueOf(realData.get("ifInsertGun").getValue());
            //0:否1:是
            if ("1".equals(ifInsertGun)) {
                return AjaxResult.success(new HashMap<String, Object>() {{
                    put("state", true);
                    put("msg", "已插枪");
                }});
            } else {
                return AjaxResult.success(new HashMap<String, Object>() {{
                    put("state", false);
                    put("msg", "请先插枪");
                }});
            }
        } else {
            return AjaxResult.success(new HashMap<String, Object>() {{
                put("state", false);
                put("msg", "请先插枪");
            }});
        }
    }

    /**
     * 开始充电
     *
     * @param
     */
    @GetMapping("/startCharging")
    @Transactional
    public AjaxResult startCharging(String custCode, String orderCode, String money, String deviceCode, String gunPos) {
        if (orderCode == null || "null".equals(orderCode) || money == null || "null".equals(money)
                || deviceCode == null || "null".equals(deviceCode) || gunPos == null || "null".equals(gunPos)) {
            return AjaxResult.error("参数错误,下发失败");
        }

        Map<String, Object> props = new HashMap<String, Object>();
        //下发充电命令
        gunPos = gunPos.substring(gunPos.length() - 2);
        Map<String, Object> stringObjectMap = remoteInstructSendService.startCharge(deviceCode, gunPos, Integer.parseInt(money), "YTSN-CDZ-N01");
//        stringObjectMap = new HashMap<String, Object>() {{
//            put("transactionNum", "20240425181250440309000200020201");
//        }};
        if (stringObjectMap != null && stringObjectMap.get("transactionNum") != null) {
            String transactionNum = stringObjectMap.get("transactionNum").toString();

            //添加到充电过程中实时数据交易订单信息
            ChargePileOrderInfo chargePileOrderInfo = new ChargePileOrderInfo();
            chargePileOrderInfo.setOrderCode(orderCode);
            chargePileOrderInfo.setTransactionNum(transactionNum);
            chargePileOrderInfo.setOpenId(custCode);

            //是否有相同的订单信息
            List<ChargePileOrderInfo> chargePileOrderInfos = chargePileOrderInfoMapper.selectChargePileOrderInfoList(chargePileOrderInfo);
            if (chargePileOrderInfos != null && chargePileOrderInfos.size() > 0) {
                //修改信息
                boolean isUpdate = chargePileOrderInfoMapper.updateChargePileOrderInfo(chargePileOrderInfo);
                if (!isUpdate) {
                    log.error("充电过程中修改实时数据失败");
                }
            } else {
                //添加信息
                boolean isAdd = chargePileOrderInfoMapper.insertChargePileOrderInfo(chargePileOrderInfo);
                if (!isAdd) {
                    log.error("充电过程中添加实时数据失败");
                }
            }

            //存入redis
            ChargePileOrderInfo redisInfo = redisCache.getCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum);
            if (redisInfo == null || redisInfo.getOrderCode() == null) {
                redisInfo = new ChargePileOrderInfo();
                redisInfo.setOrderCode(orderCode);
                redisInfo.setTransactionNum(transactionNum);
                redisInfo.setOpenId(custCode);
                redisCache.setCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum, redisInfo);
            } else if (redisInfo.getOpenId() == null) {
                redisInfo.setOpenId(custCode);
                redisCache.setCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum, redisInfo);
            }
//            else {
//                redisInfo.setOrderCode(orderCode);
//                redisCache.setCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum, redisInfo);
//            }

            return AjaxResult.success("下发成功", new HashMap<String, String>() {{
                put("transactionNum", transactionNum);
            }});

        } else {
            return AjaxResult.error("下发失败");
        }
    }

    @GetMapping("/startChargingRefund")
    @Transactional
    public WxPay startChargingRefund(String orderCode, String deviceCode, String portId) {
        //发起退款
        WxPay wxPay = new WxPay();
        //商户订单号
        wxPay.setOutTradeNo(orderCode);
        ChargeCustomOrderInfo chargeCustomOrderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(orderCode);
        //退款金额
        BigDecimal refundMoney =
                chargeCustomOrderInfo.getPaymentAmount() == null || chargeCustomOrderInfo.getPaymentAmount().compareTo(BigDecimal.ZERO) == 0 ? chargeCustomOrderInfo.getTotalMoney() : chargeCustomOrderInfo.getPaymentAmount();
        wxPay.setMoney(String.valueOf(refundMoney));
        WxPay refund = wXPayService.refund(wxPay);
        System.out.println("小程序开始充电失败，发起退款——————————————————————————————————————————————————————————————》");
        //查询充电枪是否在充电
        remoteInstructSendService.getRealData(deviceCode, portId.substring(portId.length() - 2), "YTSN-CDZ-N01");
        System.out.println("小程序开始充电失败，发送查询枪口状态指令——————————————————————————————————————————————————————————————》");
        return refund;
    }

    //查询枪口状态
    @GetMapping("/startChargingEndCharge")
    public AjaxResult startChargingEndCharge(String orderCode, String deviceCode, String portId) {
        System.out.println("小程序开始充电倒计时完毕，查询订单状态——————————————————————————————————————————————————————————————》");
        Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(portId);
        String portStatus = "";
        if (realData.containsKey("runningState")) {
            portStatus = String.valueOf(realData.get("runningState").getValue());
        }

        //查询订单状态
        ChargeCustomOrderInfo chargeCustomOrderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(orderCode);
        if ("1".equals(chargeCustomOrderInfo.getOrderInfoStatus())) {
            if ("3".equals(portStatus)) {
                //已付款 充电中 跳转充电页面
                return AjaxResult.success("充电成功", chargeCustomOrderInfo);
            } else {
                System.out.println("充电桩开始充电失败，发起退款——————————————————————————————————————————————————————————————》");
                //机器问题 充电失败
                //发起退款
                WxPay wxPay = new WxPay();
                //商户订单号
                wxPay.setOutTradeNo(orderCode);
                //退款金额
                BigDecimal refundMoney =
                        chargeCustomOrderInfo.getPaymentAmount() == null || chargeCustomOrderInfo.getPaymentAmount().compareTo(BigDecimal.ZERO) == 0 ? chargeCustomOrderInfo.getTotalMoney() : chargeCustomOrderInfo.getPaymentAmount();
                wxPay.setMoney(String.valueOf(refundMoney));
                WxPay refund = wXPayService.refund(wxPay);
                return AjaxResult.success("充电失败，已发起退款", chargeCustomOrderInfo);
            }
        } else {
            //未付款 停止充电 且 充电失败
            if ("3".equals(portStatus)) {
                //如果在充电就下发结束充电指令
                System.out.println("订单未付款，枪口正在充电，发送停止充电指令——————————————————————————————————————————————————————————————》");
                String gunPos = portId.substring(portId.length() - 2);
                remoteInstructSendService.endCharge(deviceCode, gunPos, "YTSN-CDZ-N01");
            }

            return AjaxResult.success("付款失败", chargeCustomOrderInfo);
        }
    }

    /**
     * 结束充电
     *
     * @param
     */
    @GetMapping("/endCharging")
    public AjaxResult endCharging(String transactionNum, String orderCode, String deviceCode, String gunPos) {
        gunPos = gunPos.substring(gunPos.length() - 2);
        remoteInstructSendService.endCharge(deviceCode, gunPos, "YTSN-CDZ-N01");
        return AjaxResult.success("结束充电成功");
    }

    /**
     * 结束充电
     *
     * @param
     */
    @GetMapping("/endChargingRefund")
    public AjaxResult endChargingRefund(String transactionNum, String orderCode) {
        return AjaxResult.success("结束充电成功3");
    }


    /**
     * 查询充电实时信息
     *
     * @param
     */
    @GetMapping("/queryChargingInfo")
    public AjaxResult queryChargingInfo(String transactionNum, String deviceCode, String gunPos) {
        remoteInstructSendService.getRealData(deviceCode, gunPos, "YTSN-CDZ-N01");
        ChargePileOrderInfo redisInfo = redisCache.getCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum);
        if (redisInfo == null) {
            for (int i = 0; i < 1000; i++) {
                if (i == 999) {
                    log.error("------------------------------未获取到redis中的正在充电信息----------------------------------------");
                }
                redisInfo = redisCache.getCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum);
                if (redisInfo != null && redisInfo.getSoc() != null) {
                    return AjaxResult.success(redisInfo);
                }
            }
        }

        return AjaxResult.success("查询成功", redisInfo);
    }


    /**
     * @Author:gaojikun
     * @Description: 小程序上传头像
     * @Return:AjaxResult
     */
    @PostMapping("/uploadCustomPhoto")
    public AjaxResult uploadCustomPhoto(@RequestParam("file") MultipartFile file, @RequestParam("params") String params) {
        Map<String, Object> param = JSON.parseObject(params);
        if (null == param.get("openid")) {
            return AjaxResult.error("参数错误");
        }
        Map<String, String> map = uploadImg(file, param.get("url"));
        if (null == map || StringUtils.isEmpty(map.get("url"))) {
            return AjaxResult.error("未成功上传");
        } else {
            //修改客户头像
            ChargeCustomUser chargeCustomUser = chargeCustomUserMapper.selectChargeCustomUserByOpenid(param.get("openid").toString());
            chargeCustomUser.setCustomPhoto(map.get("url"));
            int updateNum = chargeCustomUserMapper.updateChargeCustomUser(chargeCustomUser);
            if (updateNum == 1) {
                return AjaxResult.success(map);
            } else {
                return AjaxResult.error("修改失败");
            }

        }
    }

    /**
     * @Author:gaojikun
     * @Description: 小程序上传汽车照片
     * @Return:AjaxResult
     */
    @PostMapping("/uploadCarPhoto")
    public AjaxResult uploadCarPhoto(@RequestParam("file") MultipartFile file) {

        Map<String, String> map = uploadImg(file, "");
        if (null == map) {
            return AjaxResult.error("未成功上传");
        } else {
            return AjaxResult.success(map);
        }
    }

    /**
     * @Author:gaojikun
     * @Description: 小程序上传评价照片
     * @Return:AjaxResult
     */
    @PostMapping("/uploadEvaluatePhoto")
    public AjaxResult uploadEvaluatePhoto(@RequestParam("file") MultipartFile file, @RequestParam("params") String params) {
        Map<String, Object> param = JSON.parseObject(params);
        if (null == param.get("openid")) {
            return AjaxResult.error("参数错误");
        }
        Map<String, String> map = uploadImg(file, "");
        if (null == map) {
            return AjaxResult.error("未成功上传");
        } else {
            return AjaxResult.success(map);
        }

    }


    /**
     * @Author:gaojikun
     * @Description: 小程序上传图片通用方法
     * @Return:AjaxResult
     */
    public Map<String, String> uploadImg(MultipartFile file, Object fileUrl) {

//        if(null != fileUrl && !StringUtils.isEmpty(fileUrl.toString()) && !"null".equals(fileUrl.toString())){
//            //删除原图片
//            deleteFolders(fileUrl.toString());
//        }

        try {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
//            HttpServletRequest request = ServletUtils.getRequest();
//            StringBuffer serviceUrl = request.getRequestURL();
//            String contextPath = request.getServletContext().getContextPath();
//            String url = serviceUrl.delete(serviceUrl.length() - request.getRequestURI().length(), serviceUrl.length()).append(contextPath).toString() + fileName;
            Map<String, String> returnMap = new HashMap<String, String>() {{
                put("url", fileName);
                put("fileName", fileName);
                put("newFileName", FileUtils.getName(fileName));
                put("originalFilename", file.getOriginalFilename());
            }};

            return returnMap;
        } catch (Exception e) {
            System.out.println("上传图片出现异常——————————》" + e);
            return null;
        }
    }

    /**
     * 删除指定文件夹下文件
     *
     * @param filePath
     */
    public static void deleteFolders(String filePath) {
        //删除指定文件夹下文件
        Path path = Paths.get(filePath);
        try {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
                    Files.delete(file);
                    System.out.println("删除文件---》: " + file);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir,
                                                          IOException exc) throws IOException {
                    Files.delete(dir);
                    System.out.println("删除文件---》: " + dir);
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * @Author:gaojikun
     * @Description:小程序关于我们
     * @Return:AjaxResult
     */
    @GetMapping("/queryUsInfo")
    public AjaxResult queryUsInfo(ChargeFeedbook chargeFeedbook) {
        Map<String, Object> returnMap = chargeCustomOrderEvaluationMapper.queryUsInfo();
        return AjaxResult.success(returnMap);
    }

    /*
    获取token
    */
    @GetMapping("/getToken")
    public AjaxResult getToken() {
        Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
        String token = "";
        token = this.isTrueToken(keys, token);
        if ("".equals(token)) {
            token = this.isTrueToken(keys, token);
        }
        token = token.replaceAll("login_tokens:", "");
        String finalToken = token;

        return AjaxResult.success(new HashMap<String, String>() {{
            put("token", finalToken);
        }});
    }

    //验证token是否有效
    public String isTrueToken(Collection<String> keys, String token) {
        if (keys.size() == 0) {
            // 生成令牌
            String login = loginService.login("admin", "admin123", null, null);
            keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
        }
        for (String key : keys) {
            LoginUser user = null;
            try {
                user = redisCache.getCacheObject(key);
                System.out.println("");
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (user != null) {
                token = key;
                break;
            }
        }
        return token;
    }

    /*
     根据订单号查询订单信息
    */
    @GetMapping("/queryOrderStatus")
    public AjaxResult queryOrderStatus(String orderCode) {
        ChargeCustomOrderInfo chargeCustomOrderInfo = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(orderCode);
        return AjaxResult.success(chargeCustomOrderInfo);
    }

    /*
     根据客户openid查询订单列表
    */
    @GetMapping("/getChargingInfo")
    public AjaxResult getChargingInfo(ChargeCustomOrderInfo chargeCustomOrderInfo) {
        List<ChargeCustomOrderInfo> chargeCustomOrderInfos = chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoAllList(chargeCustomOrderInfo);
        return AjaxResult.success(chargeCustomOrderInfos.size());
    }

    /*
     查询评价详情
    */
    @GetMapping("/queryEvaInfo")
    public AjaxResult queryEvaInfo(String orderCode) {
        ChargeCustomOrderEvaluation chargeCustomOrderEvaluation = chargeCustomOrderEvaluationMapper.selectChargeCustomOrderEvaluationByCode(orderCode);
        return AjaxResult.success(chargeCustomOrderEvaluation);
    }

    /*
     故障问题上报
    */
    @GetMapping("/addFaultInfo")
    public AjaxResult addFaultInfo(ChargeFault chargeFault) {
        chargeFault.setCreateTime(DateUtils.getNowDate());
        int i = chargeFaultMapper.insertChargeFault(chargeFault);
        return AjaxResult.success(i);
    }

    /*
     故障问题详情
    */
    @GetMapping("/queryFaultInfo")
    public AjaxResult queryFaultInfo(Long faultId) {
        ChargeFault chargeFault = chargeFaultMapper.selectChargeFaultByDeviceFaultId(faultId);
        return AjaxResult.success(chargeFault);
    }

    /*---------------------------------------------------------------第2部分-公共信息交换-----------------------------------------------------------------*/


    /*
     * @Author      gaojikun
     * @Date        2024/5/13 14:45
     * @Description    6.2 查询充电站信息  (由数据需求方调用)
     * @Param LastQueryTime   上次查询时间    格式(“yyyy-MM-dd HH:mm:ss”)
     * @Param PageNo   查询页码  不写默认1  格式(1)
     * @Param PageSize    每页数量  不写默认10   格式(10)
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_stations_info")
    public ApsmsResult query_stations_info(TestDomain testDomain/*String LastQueryTime, int PageNo, int PageSize*/) {

        String LastQueryTime = testDomain.getLastQueryTime();
        int PageNo = testDomain.getPageNo();
        int PageSize = testDomain.getPageSize();

        Map<String, Object> returnMap = new HashMap<>();
        List<Map<String, Object>> StationsInfos = new ArrayList<>();
        //查询所有的电站信息
        List<ChargeStation> allChargeStations = chargeStationMapper.selectChargeStationList(null);
        int itemSize = allChargeStations.size();
        // java8流分页
        List<ChargeStation> chargeStations = allChargeStations.stream().skip((PageNo - 1) * PageSize).limit(PageSize).
                collect(Collectors.toList());

        for (ChargeStation chargeStation : chargeStations) {
            Map<String, Object> stationMap = new HashMap<>();
            //运营商ID 格式("123456789") 必填  9字符
            stationMap.put("OperationID", chargeStation.getOperatorCode());
            //充电站ID 格式("0000000001") 必填 设备商自定义的唯一编码  <=20字符
            stationMap.put("StationID", String.valueOf(chargeStation.getChargeStationCode()));
            //UniCode 编解码
            String UName = StringEscapeUtils.escapeJava(chargeStation.getChargeStationName());
            //充电站名称 格式("\u5154\u7535") 必填 <=50字符
            stationMap.put("StationName", UName);
            //设备所属方ID 格式("123456789") 必填 设备所属运营平台组织机构代码 9字符
            stationMap.put("EquipmentOwnerID", "");
            //充电站国家代码 格式("CN") 必填 2字符
            stationMap.put("CountryCode", "CN");
            //充电站省市辖区编码 格式("") 必填 内容填隙额参照GB/T 2260-2007 20字符
            stationMap.put("AreaCode", "");
            //UniCode 编解码
            String UAdress = StringEscapeUtils.escapeJava(chargeStation.getChargeStationAddress());
            //详细地址 格式("\u5154\u7535")必填 <=50字符
            stationMap.put("Address", UAdress);
            //站点电话 格0式("15358998547") 非必填 <=30字符
            stationMap.put("StationTel", chargeStation.getChargeStationPhone());
            //服务电话 格式("15358998547") 必填 <=30字符
            stationMap.put("ServiceTel", chargeStation.getChargeStationPhone());
            //站点类型 格式(1) 必填  1-公共 50-个人 100-公交 101-环卫 102-物流 103-出租车 255-其他 必填
            stationMap.put("StationType", Integer.parseInt(chargeStation.getChargeStationType()));
            //站点状态 格式(1) 0-未知 1-建设中 5-关闭下线 6-维护中 50-正常使用 必填
            stationMap.put("StationStatus", Integer.parseInt(chargeStation.getChargeStationStatus()));
            //车位数量 格式(0) 默认0-未知 必填
            stationMap.put("ParkNums", 0);
            //经度 GCJ-02坐标 格式(小数点后6位) 必填
            stationMap.put("StationLng", new BigDecimal(String.valueOf(chargeStation.getChargeStationLongitude())).setScale(6, RoundingMode.HALF_UP));
            //纬度 GCJ-02坐标 格式(小数点后6位) 必填
            stationMap.put("StationLat", new BigDecimal(String.valueOf(chargeStation.getChargeStationLatitude())).setScale(6, RoundingMode.HALF_UP));
            //建设场所 格式(1) 1-居民区 2-公共机构 3-企事业单位 4-写字楼 5-工业园区 6-交通枢纽 7-大型问题设施 8-城市绿地 9-大型建筑配电停车场 10-路边停车位 11-城际高速服务区 255-其他 必填
            stationMap.put("Construction", Integer.parseInt(chargeStation.getBuildingSite()));
            //站点照片  非必填
            String photoUrl = chargeStation.getChargeStationPhoto();
            String[] photoArr = {photoUrl};
            stationMap.put("Pictures", photoArr);
            //查询充电桩列表
            ChargeStationPile pile = new ChargeStationPile();
            pile.setStationId(chargeStation.getChargeStationId());
            List<ChargeStationPile> pileList = chargeStationPileMapper.getList(pile);

            List<Map<String, Object>> EquipmentInfos = new ArrayList<>();
            for (ChargeStationPile chargeStationPile : pileList) {
                List<Map<String, Object>> ConnectorInfos = new ArrayList<>();
                Map<String, Object> pileMap = new HashMap<>();
                //设备编码 格式("100000003") 设备唯一编码，对同一运营商保持唯一  必填  <=23字符
                pileMap.put("EquipmentID", chargeStationPile.getDeviceId());
                //设备生产商组织机构代码 格式("123456789") 非必填  9字符
                pileMap.put("ManufacturerID", "");
                //设备型号 格式("p3")  由设备生产商定义的设备型号  非必填  <=20字符
                pileMap.put("EquipmentModel", chargeStationPile.getEquipmentModel());
                //设备生产日期 格式("2016-04-26") 非必填 10字符
                pileMap.put("ProductionDate", chargeStationPile.getFactoryDate());
                //设备类型 格式(1) 1-直流设备 2-交流设备 3-交直流一体设备 4-无线设备 5-其他  必填
                pileMap.put("EquipmentType", chargeStationPile.getTerminalType());
                //充电设备总功率 格式(小数点后1位) 单位：kW 必填
                pileMap.put("Power", chargeStationPile.getRatedPower().setScale(1, BigDecimal.ROUND_HALF_UP));
                //设备认证流水号 格式("一号装") 非必填 <=30字符 设备名称
                pileMap.put("EquipmentName", chargeStationPile.getPileName());

                //查询充电枪列表
                ChargeStationPort port = new ChargeStationPort();
                port.setDeviceId(chargeStationPile.getDeviceId());
                List<ChargeStationPort> chargeStationPorts = chargeStationPortMapper.selectPortList(port);
                for (ChargeStationPort chargeStationPort : chargeStationPorts) {
                    Map<String, Object> portMap = new HashMap<>();
                    //充电设备接口编码 充电设备接口编码，同一运营商内编码唯一 格式("") 必填 <=26字符
                    portMap.put("ConnectorID", chargeStationPort.getId());
                    //充电设备接口类型 格式(0) 1-家用插座(模式2) 2-交流接口插座(模式3，连接方式B) 3-交流接口插头(带枪线，模式3，连接方式C) 4-直流接口枪头(带枪线，模式4) 5-无线充电座 6-其他 必填
                    portMap.put("ConnectorType", Integer.parseInt(chargeStationPort.getConnectorType()));
                    //额定电压上限 单位：V 格式(0) 必填
                    portMap.put("VoltageUpperLimits", chargeStationPort.getVoltageUpperLimits());
                    //额定电压下限 单位：V 格式(0) 必填
                    portMap.put("VoltageLowerLimits", chargeStationPort.getVoltageLowerLimits());
                    //额定电流 单位：A 格式(0) 必填
                    portMap.put("Current", chargeStationPort.getCurrent());
                    //国家标准 格式(1) 1-2011 2-2015 必填
                    portMap.put("NationalStandard", 1);
                    //额定功率 单位：kW 格式(小数点后1位) 必填
                    portMap.put("Power", chargeStationPort.getPower().setScale(1, BigDecimal.ROUND_HALF_UP));
                    ConnectorInfos.add(portMap);
                }

                pileMap.put("ConnectorInfos", ConnectorInfos);//充电设备接口信息列表 格式([]) 必填
                EquipmentInfos.add(pileMap);
            }
            stationMap.put("EquipmentInfos", EquipmentInfos);//充电设备信息 格式([])
            StationsInfos.add(stationMap);
        }

        returnMap.put("ItemSize", itemSize);//总记录条数(符合条件的电站总数) 格式("0")
        int pageCount = (itemSize + PageSize - 1) / PageSize;
        returnMap.put("PageCount", pageCount);//页面码总数 格式(0)
        returnMap.put("PageNo", PageNo);//当前页数 格式(0)
        returnMap.put("StationsInfos", StationsInfos);//充电站信息列表 格式([])

//        Map<String, Object> returnMap = new HashMap<String, Object>() {{
//            put("ItemSize", 1);//总记录条数(符合条件的电站总数) 格式("0")
//            put("PageCount", 1);//页面码总数 格式(0)
//            put("PageNo", 1);//当前页数 格式(0)
//            put("StationsInfos", new HashMap<String, Object>() {{//充电站信息列表 格式([])
//                put("OperationID", "123456789");//运营商ID 格式("") 必填  9字符
//                put("StationID", "0000000001");//充电站ID 格式("") 必填 设备商自定义的唯一编码  <=20字符
//                put("StationName", "\u5154\u7535");//充电站名称 格式("") 必填 <=50字符
//                put("EquipmentOwnerID", "123456789");//设备所属方ID 格式("") 必填 设备所属运营平台组织机构代码 9字符
//                put("CountryCode", "CN");//充电站国家代码 格式("") 必填 2字符
//                put("AreaCode", "441781");//充电站省市辖区编码 格式("") 必填 内容填隙额参照GB/T 2260-2007 20字符
//                put("Address", "\u5154\u7535");//详细地址 格式("")必填 <=50字符
//                put("StationTel", "123456789");//站点电话 格0式("") 非必填 <=30字符
//                put("ServiceTel", "123456789");//服务电话 格式("") 必填 <=30字符
//                put("StationType", 1);//站点类型 格式(1) 必填  1-公共 50-个人 100-公交 101-环卫 102-物流 103-出租车 255-其他 必填
//                put("StationStatus", 50);//站点状态 格式(1) 0-未知 1-建设中 5-关闭下线 6-维护中 50-正常使用 必填
//                put("ParkNums", 3);//车位数量 格式(0) 默认0-未知 必填
//                put("StationLng", 119.97049);//经度 GCJ-02坐标 格式(小数点后6位) 必填
//                put("StationLat", 31.717877);//纬度 GCJ-02坐标 格式(小数点后6位) 必填
//                put("Construction", 1);//建设场所 格式(1) 1-居民区 2-公共机构 3-企事业单位 4-写字楼 5-工业园区 6-交通枢纽 7-大型问题设施 8-城市绿地 9-大型建筑配电停车场 10-路边停车位 11-城际高速服务区 255-其他 必填
//                put("Pictures", new ArrayList<String>() {{//站点照片 格式([]) 非必填
////                    add("http:\/\/www.xx.com\/xxx");
////                    add("http:\/\/www.xx.com\/xxx");
//                }});
//                put("EquipmentInfos", new ArrayList<Map<String, Object>>() {{//充电设备信息 格式([])
//                    put("EquipmentID", "100000003");//设备编码 格式("") 设备唯一编码，对同一运营商保持唯一  必填  <=23字符
//                    put("ManufacturerID", "123456789");//设备生产商组织机构代码 格式("") 非必填  9字符
//                    put("EquipmentModel", "p3");//设备型号 格式("")  由设备生产商定义的设备型号  非必填  <=20字符
//                    put("ProductionDate", "2016-04-26");//设备生产日期 格式("") 非必填 10字符
//                    put("EquipmentType", 3);//设备类型 格式(1) 1-直流设备 2-交流设备 3-交直流一体设备 4-无线设备 5-其他  必填
//                    put("Power", 3.3);//充电设备总功率 格式(小数点后1位) 单位：kW 必填
//                    put("EquipmentName", "一号桩");//设备认证流水号 格式("") 非必填 <=30字符
//                    put("ConnectorInfos", new ArrayList<Map<String, Object>>() {{//充电设备接口信息列表 格式([]) 必填
//                        put("ConnectorID", "1");//充电设备接口编码 充电设备接口编码，同一运营商内编码唯一 格式("") 必填 <=26字符
//                        put("ConnectorType", 1);//充电设备接口类型 格式(0) 1-家用插座(模式2) 2-交流接口插座(模式3，连接方式B) 3-交流接口插头(带枪线，模式3，连接方式C) 4-直流接口枪头(带枪线，模式4) 5-无线充电座 6-其他 必填
//                        put("VoltageUpperLimits", 220);//额定电压上限 单位：V 格式(0) 必填
//                        put("VoltageLowerLimits", 220);//额定电压下限 单位：V 格式(0) 必填
//                        put("Current", 15);//额定电流 单位：A 格式(0) 必填
//                        put("NationalStandard", 1);//国家标准 格式(1) 1-2011 2-2015 必填
//                        put("Power", 3.3);//额定功率 单位：kW 格式(小数点后1位) 必填
//                    }});
//                }});
//            }});
//        }};


        return ApsmsResult.success(0, "", returnMap, "");
    }


    /*
     * @Author      gaojikun
     * @Date        2024/5/13 14:45
     * @Description    6.3 设备状态变化推送,推送最新的状态到合作方  (由数据需求方实现此接口，基础设施运营商方调用)
     * @Param ConnectorStatusInfo  充电设备接口状态  格式(“”)
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/notification_stationStatus")
    public ApsmsResult notification_stationStatus(/*ConnectorStatusInfo ConnectorStatusInfo*/) {
        Map<String, Object> returnMap = new HashMap<String, Object>() {{
            put("Status", 0);//返回参数  Status 状态 格式(0) 0-接受 1-丢弃/忽略，不需要重试
        }};

        return null;
    }


    /*
     * @Author      gaojikun
     * @Date        2024/5/13 14:45
     * @Description    6.4 设备接口状态查询  (由数据需求方调用)
     * @Param StationIDs   充电站ID列表   格式([])
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_station_status")
    public ApsmsResult query_station_status(TestDomain testDomain/*String StationIDs*/) {
        List<String> StationIDs = testDomain.getStationIDs();

        Map<String, Object> returnMap = new HashMap<>();

        ArrayList<Map<String, Object>> StationStatusInfos = new ArrayList<>();

        for (String stationID : StationIDs) {
            Map<String, Object> stationMap = new HashMap<>();
            stationMap.put("StaionID", stationID);

            //根据充电桩查出枪的状态
            ChargeStationPort chargeStationPort = new ChargeStationPort();
            chargeStationPort.setDeviceId(stationID);
            List<ChargeStationPort> portTagList = chargeStationPortMapper.selectPortList(chargeStationPort);

            ArrayList<Map<String, Object>> ConnectorStatusInfos = new ArrayList<>();
            for (ChargeStationPort port : portTagList) {
                Map<String, Object> ConnectorMap = new HashMap<>();
                ConnectorMap.put("ConnectorID", port.getId());

                Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(port.getId());
                if (realData.containsKey("ifInsertGun") && realData.containsKey("runningState")) {
                    String ifInsertGun = String.valueOf(realData.get("ifInsertGun").getValue());//ifInsertGun 是否插枪 0-否 1-是
                    String runningState = String.valueOf(realData.get("runningState").getValue());//runningState 运行状态  0-离线 1-故障 2-空闲 3-充电

                    if ("0".equals(runningState)) {//设备离线
                        ConnectorMap.put("Status", 0);
                    } else if ("1".equals(runningState)) {//设备故障
                        ConnectorMap.put("Status", 255);
                    } else {
                        if ("1".equals(ifInsertGun)) {//已插枪
                            if ("2".equals(runningState)) {//正常
                                ConnectorMap.put("Status", 2);//占用(未充电)
                            }
                            if ("3".equals(runningState)) {//充电
                                ConnectorMap.put("Status", 3);//占用(充电中)
                            }
                        } else {
                            ConnectorMap.put("Status", 1);//正常
                        }
                    }
                } else {
                    ConnectorMap.put("Status", 0);
                }

                ConnectorStatusInfos.add(ConnectorMap);
            }
            stationMap.put("ConnectorStatusInfos", ConnectorStatusInfos);

            StationStatusInfos.add(stationMap);
        }

        returnMap.put("Total", StationStatusInfos.size());
        returnMap.put("StationStatusInfos", StationStatusInfos);

//        Map<String, Object> returnMap = new HashMap<String, Object>() {{
//            put("Total", 1);//
//            put("StationStatusInfos", new ArrayList<Map<String, Object>>() {{
//                put("StaionID", "111111");//充电站ID 运营商自定义的唯一编码，不足长度在前方补0 格式(“”) 必填 <=20字符
//                put("ConnectorStatusInfos", new ArrayList<Map<String, Object>>() {{//充电设备接口状态列表  所有充电设备接口的状态  格式(“[]”)  必填
//                    put("ConnectorID", "1");//充电设备接口编码  充电设备接口编码,同一运营商内唯一  格式(“”)  必填
//                    put("Status", 4);//充电设备接口状态  格式(0) 0-离网 1-空闲 2-占用(未充电) 3-占用(充电中) 4-占用(预约锁定) 255-故障  必填
//                }});
//            }});
//        }};

        return ApsmsResult.success(0, "", returnMap, "");
    }


    /*
     * @Author      gaojikun
     * @Date        2024/5/13 14:45
     * @Description    6.5 查询统计信息  (由数据需求方调用)
     * @Param StationIDs   充电站ID列表   格式(“”)
     * @Param StartTime   统计开始时间   格式(“yyyy-MM-dd”)
     * @Param EndTime   统计结束时间   格式(“yyyy-MM-dd”)
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_station_stats")
    public ApsmsResult query_station_stats(TestDomain testDomain/*String StationIDs, String StartTime, String EndTime*/) {
        String StationIDs = testDomain.getStationID();
        String StartTime = testDomain.getStartTime();
        String EndTime = testDomain.getEndTime();

        Map<String, Object> returnMap = new HashMap<>();
        BigDecimal StationElectricity = BigDecimal.ZERO;//充电站累计电量
        //根据充电站ID查询充电桩   code
        List<String> deviceIdList = chargeStationPileMapper.getDeviceIdList(StationIDs);
        List<Map<String, Object>> EquipmentStatsInfos = new ArrayList<>();//充电桩
        for (String deviceId : deviceIdList) {
            BigDecimal EquipmentElectricity = BigDecimal.ZERO;//充电桩累计电量
            List<Map<String, Object>> ConnectorStatsInfos = new ArrayList<>();//充电枪
            List<Map<String, Object>> stringObjectList = chargeCustomOrderInfoMapper.queryStationStats(deviceId, StartTime, EndTime);
            for (Map<String, Object> stringObjectMap : stringObjectList) {
                BigDecimal ConnectorElectricity = new BigDecimal(stringObjectMap.get("ConnectorElectricity").toString()).setScale(1, BigDecimal.ROUND_HALF_UP);
                ConnectorStatsInfos.add(new HashMap<String, Object>() {{
                    put("ConnectorID", deviceId + stringObjectMap.get("gunPos").toString());
                    put("ConnectorElectricity", ConnectorElectricity);
                }});
                EquipmentElectricity = EquipmentElectricity.add(ConnectorElectricity);
                StationElectricity = StationElectricity.add(ConnectorElectricity);
            }

            EquipmentStatsInfos.add(new HashMap<String, Object>() {{
                put("EquipmentID", deviceId);
//                put("EquipmentElectricity", EquipmentElectricity.setScale(1, BigDecimal.ROUND_HALF_UP));
                put("ConnectorStatsInfos", ConnectorStatsInfos);
            }});


        }

        returnMap.put("StationStats", new HashMap<String, Object>() {{
            put("StationID", StationIDs);
            put("StartTime", StartTime);
            put("EndTime", EndTime);
//            put("StationElectricity", StationElectricity.setScale(1, BigDecimal.ROUND_HALF_UP));
            put("EquipmentStatsInfos", EquipmentStatsInfos);
        }});


//        Map<String, Object> returnMap = new HashMap<String, Object>() {{
//            put("StationStats", new HashMap<String, Object>() {{
//                put("StationID", "11111111");//充电站ID   站点编号  格式(“”)  <=20字符  必填
//                put("StartTime", "2015-10-01");//统计的开始时间   格式(“yyyy-MM-dd”)  <=20字符  必填
//                put("EndTime", "2015-10-02");//统计的结束时间   格式(“yyyy-MM-dd”)  <=20字符  必填
//                put("StationElectricity", "");//充电站累计电量  单位：kWh 格式(小数点后1位)   必填
//                put("EquipmentStatsInfos", new ArrayList<Map<String, Object>>() {{//充电设备统计信息列表  格式([])  必填
//                    add(new HashMap<String, Object>() {{
//                        put("EquipmentID", "1000001");//设备编号  设备唯一编码。对同一运营商，保证唯一   格式(“”)  <=23字符  必填
//                        put("EquipmentElectricity", 100);//充电设备接口累计电量  单位：kWh  格式(保留小数点后1位)  必填
//                        put("ConnectorStatsInfos", new ArrayList<Map<String, Object>>() {{//充电设备接口统计信息列表  充电设备的所有充电接口统计对象  格式([])  必填
//                            put("ConnectorID", "100000101");//充电设备接口编码  充电设备接口编码，对同一运营商，保证唯一 站点编号  格式(“”)  <=26字符  必填
//                            put("ConnectorElectricity", 100);//充电设备接口累计电量  单位：kWh  格式(保留小数点后1位)  必填
//                        }});
//                    }});
//                }});
//            }});
//        }};

        return ApsmsResult.success(0, "", returnMap, "");
    }

    /*---------------------------------------------------------------第3部分-业务信息交换-----------------------------------------------------------------*/

    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.2 请求设备认证  (由客户归属运营商调用)
     * @Param EquipAuthSeq   设备认证流水号    格式(运营商ID+唯一编码) 27字符
     * @Param ConnectorID    充电设备接口编码    ???? 格式("")   枪口ID
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_equip_auth")
    public ApsmsResult query_equip_auth(TestDomain testDomain/*String EquipAuthSeq, String ConnectorID*/) {

        String EquipAuthSeq = testDomain.getEquipAuthSeq();
        String ConnectorID = testDomain.getConnectorID();

        Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(ConnectorID);
        if (realData.containsKey("ifInsertGun") && realData.containsKey("runningState")) {
            String ifInsertGun = String.valueOf(realData.get("ifInsertGun").getValue());//ifInsertGun 是否插枪 0-否 1-是
            String runningState = String.valueOf(realData.get("runningState").getValue());//runningState 运行状态  0-离线 1-故障 2-空闲 3-充电

            if ("0".equals(runningState)) {//设备离线
                return ApsmsResult.success(0, "", new HashMap<String, Object>() {{
                    put("EquipAuthSeq", EquipAuthSeq);
                    put("SuccStat", 0);
                    put("FailReason", 2);
                }}, "");
            }
            if ("1".equals(runningState)) {//设备故障
                return ApsmsResult.success(0, "", new HashMap<String, Object>() {{
                    put("EquipAuthSeq", EquipAuthSeq);
                    put("SuccStat", 0);
                    put("FailReason", 2);
                }}, "");
            }
            if ("0".equals(ifInsertGun)) {//设备为插枪
                return ApsmsResult.success(0, "", new HashMap<String, Object>() {{
                    put("EquipAuthSeq", EquipAuthSeq);
                    put("SuccStat", 0);
                    put("FailReason", 1);
                }}, "");
            }

            //设备正常
            return ApsmsResult.success(0, "", new HashMap<String, Object>() {{
                put("EquipAuthSeq", EquipAuthSeq);
                put("SuccStat", 0);
                put("FailReason", 0);
            }}, "");
        }

        Map<String, Object> returnMap = new HashMap<String, Object>() {{
            put("EquipAuthSeq", EquipAuthSeq);//设备认证流水号 格式("") 27字符
            put("ConnectorID", ConnectorID);//充电设备接口编码 格式("")
            put("SuccStat", 1);//操作结果  0-成功 1-失败 格式(0)
            put("FailReason", 2);//失败原因 0-无 1-此设备尚未插枪 2-设备检测失败 3~99-自定义 格式(0)
        }};
        return ApsmsResult.success(0, "", returnMap, "");
    }

    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.3 查询有无策略信息结果 (向客户归属运营商获取)
     * @Param EquipBizSeq   业务策略查询流水号    格式(运营商ID+唯一编码) 27字符
     * @Param ConnectorID    充电设备接口编码    ???? 格式("")
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_equip_business_policy")
    public ApsmsResult query_equip_business_policy() {
        Map<String, Object> returnMap = new HashMap<String, Object>() {{
            put("EquipAuthSeq", "EquipAuthSeq");//业务策略查询流水号 格式("")
            put("ConnectorID", "ConnectorID");//充电设备接口编码 格式("")
            put("SuccStat", 0);//操作结果哦 0-成功 1-失败 格式(0)
            put("FailReason", 0);//失败原因 0-无 1-此设尚备未插枪 2-设备检测失败 3~99-自定义 格式(0)
            put("SumPeriod", 1);//时段数 0~32 格式(0)
            put("PolicyInfos", new ArrayList<Map<String, Object>>() {{
                add(new HashMap<String, Object>() {{
                    put("StartTime", "030234");//时段起始时间 格式("HHmmss") 6字符 格式(“”)
                    put("ElecPrice", 1.2731);//时段电费 小数点后四位 格式(0.00)
                    put("ServicePrice", 0.3713);//时段服务费 小数点后四位 格式(0.00)
                }});
            }});
        }};
        return null;
    }


    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.4 请求充电接口 (由客户归属运营商调用)
     * @Param StartChargeSeq   充电订单号    格式(运营商ID+唯一编码) 27字符
     * @Param ConnectorID    充电设备接口编码    ????
     * @Param QRCode    二维码其他信息
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_start_charge")
    public ApsmsResult query_start_charge(TestDomain testDomain/*String StartChargeSeq, String ConnectorID, String QRCode*/) {

        String StartChargeSeq = testDomain.getStartChargeSeq();
        String ConnectorID = testDomain.getConnectorID();
        String QRCode = testDomain.getQRCode();
        //查询设备
        Map<String, Object> returnMap = new HashMap<String, Object>();
        ChargeStationPort port = chargeStationPortMapper.selectByPrimaryKey(ConnectorID);
        if (port == null) {
            returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式("")
            returnMap.put("StartChargeSeqStat", 1);//充电订单状态 格式(0)
            returnMap.put("ConnectorID", ConnectorID); //充电设备接口编码 格式("")
            returnMap.put("SuccStat", 1);//操作结果 0-成功 1-失败 格式(0)
            returnMap.put("FailReason", 1);//失败原因 0-无 1-此设备不存在 2-此设备离线 3~99-自定义 格式(0)

            return ApsmsResult.success(0, "", returnMap, "");
        }

        Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(ConnectorID);
        if (realData.containsKey("ifInsertGun") && realData.containsKey("runningState")) {
            String ifInsertGun = String.valueOf(realData.get("ifInsertGun").getValue());//ifInsertGun 是否插枪 0-否 1-是
            String runningState = String.valueOf(realData.get("runningState").getValue());//runningState 运行状态  0-离线 1-故障 2-空闲 3-充电
            if ("1".equals(ifInsertGun) && "2".equals(runningState)) {
                //空闲已插枪算插枪
                port.setServiceStatus("4");
            }
//            //查询设备是否在线
//            if () {
//                returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式("")
//                returnMap.put("StartChargeSeqStat", 1);//充电订单状态 格式(0)
//                returnMap.put("ConnectorID", ConnectorID); //充电设备接口编码 格式("")
//                returnMap.put("SuccStat", 1);//操作结果 0-成功 1-失败 格式(0)
//                returnMap.put("FailReason", 2);//失败原因 0-无 1-此设备不存在 2-此设备离线 3~99-自定义 格式(0)
//            }
        }

        String deviceCode = ConnectorID.substring(0, ConnectorID.length() - 2);
        String gunPos = ConnectorID.substring(ConnectorID.length() - 2);
        //下发充电命令
        Map<String, Object> stringObjectMap = remoteInstructSendService.startCharge(deviceCode, gunPos, 0, "YTSN-CDZ-N01");
        ChargeOtherOrderInfo chargeOtherOrderInfo = new ChargeOtherOrderInfo();

        if (stringObjectMap != null && stringObjectMap.get("transactionNum") != null) {
            String transactionNum = stringObjectMap.get("transactionNum").toString();

            //添加到充电过程中实时数据交易订单信息
            ChargePileOrderInfo chargePileOrderInfo = new ChargePileOrderInfo();
            chargePileOrderInfo.setOrderCode(StartChargeSeq);
            chargePileOrderInfo.setTransactionNum(transactionNum);

            //是否有相同的订单信息
            List<ChargePileOrderInfo> chargePileOrderInfos = chargePileOrderInfoMapper.selectChargePileOrderInfoList(chargePileOrderInfo);
            if (chargePileOrderInfos != null && chargePileOrderInfos.size() > 0) {
                //修改信息
                boolean isUpdate = chargePileOrderInfoMapper.updateChargePileOrderInfo(chargePileOrderInfo);
                if (!isUpdate) {
                    log.error("充电过程中修改实时数据失败");
                }
            } else {
                //添加信息
                boolean isAdd = chargePileOrderInfoMapper.insertChargePileOrderInfo(chargePileOrderInfo);
                if (!isAdd) {
                    log.error("充电过程中添加实时数据失败");
                }
            }

            //存入redis
            ChargePileOrderInfo redisInfo = redisCache.getCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum);
            if (redisInfo == null || redisInfo.getOrderCode() == null) {
                redisInfo = new ChargePileOrderInfo();
                redisInfo.setOrderCode(StartChargeSeq);
                redisInfo.setTransactionNum(transactionNum);
                redisCache.setCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum, redisInfo);
            } else if (redisInfo.getOpenId() == null) {
                redisCache.setCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, transactionNum, redisInfo);
            }

            //添加到第三方订单表
            chargeOtherOrderInfo.setTransactionNum(transactionNum);
            chargeOtherOrderInfo.setOtherOrderCode(StartChargeSeq);
            //场站
            ChargeStationPort portInfo = chargeStationPortMapper.selectByPrimaryKey(ConnectorID);
            //策略
            ChargeStationPriceTactics chargeStationPriceTactics = new ChargeStationPriceTactics();
            chargeStationPriceTactics.setStationCode(portInfo.getStationCode());
            chargeStationPriceTactics.setIsDefault("0");
            ChargeStationPriceTactics stationNowTactics = chargeStationPriceTacticsService.getStationNowTactics(chargeStationPriceTactics);
            if (stationNowTactics != null) {
                chargeOtherOrderInfo.setPriceTypeCode(stationNowTactics.getPriceTypeCode());//计费模版code
                chargeOtherOrderInfo.setPriceTypeName(stationNowTactics.getTacticsName());//策略name
            }

            boolean b = chargeOtherOrderInfoService.insertChargeOtherOrderInfo(chargeOtherOrderInfo);

        } else {
            //下发失败
            returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式("")
            returnMap.put("StartChargeSeqStat", 0);//充电订单状态 格式(0)
            returnMap.put("ConnectorID", ConnectorID); //充电设备接口编码 格式("")
            returnMap.put("SuccStat", 1);//操作结果 0-成功 1-失败 格式(0)
            returnMap.put("FailReason", 3);//失败原因 0-无 1-此设备不存在 2-此设备离线 3~99-自定义 格式(0)
            return ApsmsResult.success(0, "", returnMap, "");
        }

//        Map<String, Object> returnMap = new HashMap<String, Object>() {{
//            put("StartChargeSeq", StartChargeSeq);//充电订单号 格式("")
//            put("StartChargeSeqStat", 1);//充电订单状态 格式(0)
//            put("ConnectorID", ConnectorID); //充电设备接口编码 格式("")
//            put("SuccStat", 0);//操作结果 0-成功 1-失败 格式(0)
//            put("FailReason", 0);//失败原因 0-无 1-此设备不存在 2-此设备离线 3~99-自定义 格式(0)
//        }};

        return ApsmsResult.success(0, "", returnMap, "");
    }


    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.5 推送启动电结果 (向客户归属运营商获取)
     * @Param StartChargeSeq   充电订单号    格式(运营商ID+唯一编码) 27字符
     * @Param StartChargeSeqSrat    充电订单状态 1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(0)
     * @Param ConnectorID    充电设备接口编码    ???? 格式("")
     * @Param StartTime    充电启动时间  格式("yyyy-MM-dd HH:mm:ss")
     * @Param IdentCode    停止充电验证码  启动充电是收到的验证码，用于点状手动停止充电 格式("")
     * @Return ApsmsResult
     * @Since version 1.0
     */
    public ApsmsResult notification_start_charge_result(String StartChargeSeq, String StartChargeSeqSrat, String ConnectorID,
                                                        String StartTime, String IdentCode) {

        //参数拼装
        String url = "";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("StartChargeSeq", StartChargeSeq);//充电订单号    格式(运营商ID+唯一编码) 27字符
        jsonObject.put("StartChargeSeqSrat", StartChargeSeqSrat);//充电订单状态 1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(0)
        jsonObject.put("ConnectorID", ConnectorID);//充电设备接口编码    ???? 格式("")
        jsonObject.put("StartTime", StartTime);//充电启动时间  格式("yyyy-MM-dd HH:mm:ss")
        jsonObject.put("IdentCode", IdentCode);//停止充电验证码  启动充电是收到的验证码，用于点状手动停止充电 格式("")
        //推送启动充电结果
        String reqJsonStr = JsonUtil.objToString(jsonObject);
        JSONObject returnInfo = null;
        try {
            returnInfo = JSON.parseObject(HttpClientSslUtils.doPost(url, reqJsonStr));
            Map<String, Object> returnMap = (Map) JSON.parse(String.valueOf(returnInfo));
            String returnSeq = returnMap.get("StartChargeSeq").toString();
            int SuccStat = Integer.parseInt(returnMap.get("SuccStat").toString());
            int FailReason = Integer.parseInt(returnMap.get("FailReason").toString());

            if (returnSeq.equals(StartChargeSeq)) {
                if (0 == SuccStat) {
                    //推送成功
                } else if (1 == SuccStat) {
                    //推送失败
                    if (1 == FailReason) {
                        //接受失败
                    }
                }
            } else {
                //不匹配
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        //返回的信息
//        Map<String, Object> returnMap = new HashMap<String, Object>() {{
//            put("StartChargeSeq", "StartChargeSeq");//充电订单号 格式("")
//            put("SuccStat", 0);//操作结果 0-成功 1-失败 格式(0)
//            put("FailReason", 0);//失败原因 0-无 1-接收失败 格式(0)
//        }};
        return null;
    }


    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.6 查询充电状态 (由客户归属运营商调用)
     * @Param StartChargeSeq   充电订单号    格式(运营商ID+唯一编码) 27字符
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_equip_charge_status")
    public ApsmsResult query_equip_charge_status(String StartChargeSeq) {

        //查看第三方订单
        ChargeOtherOrderInfo chargeOtherOrderInfo = chargeOtherOrderInfoMapper.selectChargeOtherOrderInfoByOtherOrderCode(StartChargeSeq);

        ChargePileOrderInfo redisInfo = redisCache.getCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, chargeOtherOrderInfo.getTransactionNum());

        redisInfo = chargePileOrderInfoMapper.selectChargePileOrderInfoByCode(StartChargeSeq);

        //1-充电中;2-已完成;3-取消;4-故障
        int orderStatus = 0;
        if (null == chargeOtherOrderInfo.getOrderStatus()) {
            orderStatus = 5;
        } else {
            orderStatus = Integer.parseInt(chargeOtherOrderInfo.getOrderStatus());
            if (1 == orderStatus) {
                orderStatus = 2;
            } else if (2 == orderStatus) {
                orderStatus = 4;
            } else {
                orderStatus = 5;
            }
        }

        String portId = redisInfo.getPileNumber() + redisInfo.getGunNumber();
        Map<String, DeviceProperty> realData = remoteInstructSendService.getRealData(portId);
        String portState = "1";
        //  1-空闲 2-占用(未充电) 3-占用(充电中) 4-占用(预约锁定) 255-故障 格式(0)
        if (realData.containsKey("ifInsertGun") && realData.containsKey("runningState")) {
            String ifInsertGun = String.valueOf(realData.get("ifInsertGun").getValue());//ifInsertGun 是否插枪 0-否 1-是
            String runningState = String.valueOf(realData.get("runningState").getValue());//runningState 运行状态  0-离线 1-故障 2-空闲 3-充电
            if ("1".equals(ifInsertGun) && "2".equals(runningState)) {
                //占用(未充电)
                portState = "2";
            } else if ("1".equals(ifInsertGun) && "3".equals(runningState)) {
                //占用(充电中)
                portState = "3";
            } else {
                if ("2".equals(runningState)) {
                    //空闲
                    portState = "1";
                } else {
                    //故障
                    portState = "255";
                }
            }
        }

        String chargeInfoBefore = redisInfo.getChargeInfo();
        JSONObject jsonObject = JSONObject.parseObject(chargeInfoBefore);
        Map<String, Map<String, Object>> map = jsonObject.toJavaObject(Map.class);
        Map<String, Map<String, Object>> result = new LinkedHashMap<>();
        map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(x -> result.put(x.getKey(), x.getValue()));
        List<Map.Entry<String, Map<String, Object>>> collect = result.entrySet().stream().collect(Collectors.toList());
        Map.Entry<String, Map<String, Object>> stringMapEntry = collect.get(collect.size() - 1);
        String key = stringMapEntry.getKey();

        Map<String, Object> ChargeDetailsMap = new HashMap<>();
        try {
            //计费策略
            String priceTypeCode = chargeOtherOrderInfo.getPriceTypeCode();
            String priceTypeName = chargeOtherOrderInfo.getPriceTypeName();
            ChargeCustomOrderInfo chargeCustomOrderInfo = new ChargeCustomOrderInfo();
            chargeCustomOrderInfo.setPriceTypeCode(priceTypeCode);
            chargeCustomOrderInfo.setStartTime(chargeOtherOrderInfo.getStartTime());
            chargeCustomOrderInfo.setEndTime(DateUtils.getNowDate());
            chargeCustomOrderInfo.setTotalPower(chargeOtherOrderInfo.getTotalPower());
            //获取价格信息
            ChargeDetailsMap = chargeCustomOrderInfoService.getOrderPriceList(chargeCustomOrderInfo);

        } catch (Exception e) {
            e.printStackTrace();
            log.error("------------------------------query_equip_charge_status计算区间价格信息异常----------------------------------------");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
        returnMap.put("StartChargeSeqSrat", orderStatus);//充电线订单状态   1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(0)
        returnMap.put("ConnectorID", portId);//充电设备接口编码 格式(“”)
        returnMap.put("ConnectorStatus", Integer.parseInt(portState));//充电设备接口状态 1-空闲 2-占用(未充电) 3-占用(充电中) 4-占用(预约锁定) 255-故障 格式(0)
        returnMap.put("CurrentA", 0.00);//A相电流 单位A 默认0 含直流 格式(0.00)
        returnMap.put("CurrentB", 0.00);//B相电流 单位A 默认0 格式(0.00)
        returnMap.put("CurrentC", 0.00);//C相电流 单位A 默认0 格式(0.00)
        returnMap.put("VoltageA", 0.00);//A相电压 单位A 默认0 含直流 格式(0.00)
        returnMap.put("VoltageB", 0.00);//B相电压 单位A 默认0 格式(0.00)
        returnMap.put("VoltageC", 0.00);//C相电压 单位A 默认0 格式(0.00)
        returnMap.put("Soc", redisInfo.getSoc() == null ? 0D : Double.parseDouble(redisInfo.getSoc()));//电池剩余电量 默认0 格式(0.00)
        returnMap.put("StartTime", sdf.format(redisInfo.getStartTime()));//开始充电时间 格式("yyyy-MM-dd HH:mm:ss")
        returnMap.put("EndTime", key);//本次采样时间 格式("yyyy-MM-dd HH:mm:ss")
        returnMap.put("TotalPower", redisInfo.getChargeKwh() == null ? 0D : Double.parseDouble(redisInfo.getChargeKwh()));//累计充电量 单位:度 小数点后2位 格式(0.00)
        returnMap.put("ElecMoney", new BigDecimal(String.valueOf(ChargeDetailsMap.get("electricityPrice"))));//累计电费 单位:元 小数点后2位 格式(0.00)
        returnMap.put("ServiceMoney", new BigDecimal(String.valueOf(ChargeDetailsMap.get("serviceCharge"))));//累计服务费 单位:元 小数点后2位 格式(0.00)
        returnMap.put("TotalMoney", redisInfo.getChargeMoney() == null ? 0D : Double.parseDouble(String.valueOf(redisInfo.getChargeMoney())));//累计总金额 单位:元 小数点后2位 格式(0.00)
        returnMap.put("SumPeriod", Integer.parseInt(String.valueOf(ChargeDetailsMap.get("SumPeriod"))));//时段数 0~32 格式(0)
        returnMap.put("ChargeDetails", (ArrayList<Map<String, Object>>) ChargeDetailsMap.get("ChargeDetails"));
//            returnMap.put("ChargeDetails", new ArrayList<Map<String, Object>>() {{
//                add(new HashMap<String, Object>() {{
//                    put("DetailsStartTime", "");//开始时间 格式("yyyy-MM-dd HH:mm:ss")
//                    put("DetailsEndTime", "");//结束时间 格式("yyyy-MM-dd HH:mm:ss")
//                    put("ElecPrice", 0.00);//时段电价 小数点后4位 格式(0.00)
//                    put("ServicePrice", 0.00);//时段电价 小数点后4位 格式(0.00)
//                    put("DetailPower", 0.00);//时段充电量 单位:度 小数点后2位 格式(0.00)
//                    put("DetailElecMoney", 0.00);//时段电费 小数点后2位 格式(0.00)
//                    put("DetailServiceMoney", 0.00);//时段服务费 小数点后2位 格式(0.00)
//                }});
//            }});//充电明细信息


        return ApsmsResult.success(0, "", returnMap, "");
    }


    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.7 推送充电状态 (向客户归属运营商获取)
     * @Param StartChargeSeq   充电订单号    格式(运营商ID+唯一编码) 27字符 格式(“”)
     * @Param StartChargeSeqStat   充电订单状态    1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(1)
     * @Param ConnectorID    充电设备接口编码    ??? 格式(“”)
     * @Param ConnectorStatus    充电设备接口状态   1-(空闲) 2-占用(未充电) 3-占用(充电中) 4-占用(预约锁定) 255-(故障) 格式(1)
     * @Param CurrentA A相电流 单位A 默认0 含直流 格式(0.00)
     * @Param CurrentB B相电流 单位A 默认0 格式(0.00)
     * @Param CurrentC C相电流 单位A 默认0 格式(0.00)
     * @Param VoltageA A相电压 单位A 默认0 含直流 格式(0.00)
     * @Param VoltageB B相电压 单位A 默认0 格式(0.00)
     * @Param VoltageC C相电压 单位A 默认0 格式(0.00)
     * @Param Soc 电池剩余电量 默认0 格式(0.00)
     * @Param StartTime 开始充电时间 格式(“yyyy-MM-dd HH:mm:ss”)
     * @Param EndTime 本次采样时间 格式(“yyyy-MM-dd HH:mm:ss”)
     * @Param TotalPower 累计充电量 单位:度 小数点后2位 格式(0.00)
     * @Param ElecMoney 累计电费 单位:元 小数点后2位 格式(0.00)
     * @Param ServiceMoney 累计服务费 单位:元 小数点后2位 格式(0.00)
     * @Param TotalMoney 累计总金额 单位:元 小数点后2位 格式(0.00)
     * @Param SumPeriod 时段数 0~32 格式(1)
     * @Param ChargeDetails 充电明细信息 见6.6
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/notification_equio_charge_status")
    public ApsmsResult notification_equio_charge_status(String StartChargeSeq, String StartChargeSeqStat, String ConnectorID,
                                                        String ConnectorStatus, String CurrentA, String CurrentB, String CurrentC, String VoltageA, String VoltageB, String VoltageC,
                                                        String Soc, String StartTime, String EndTime, String TotalPower, String ElecMoney, String ServiceMoney, String TotalMoney,
                                                        String SumPeriod, String ChargeDetails) {

        String url = "";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("StartChargeSeq", StartChargeSeq);
        jsonObject.put("StartChargeSeqStat", StartChargeSeqStat);
        jsonObject.put("ConnectorID", ConnectorID);
        jsonObject.put("ConnectorStatus", ConnectorStatus);
        jsonObject.put("CurrentA", CurrentA);
        jsonObject.put("CurrentB", CurrentB);
        jsonObject.put("CurrentC", CurrentC);
        jsonObject.put("VoltageA", VoltageA);
        jsonObject.put("VoltageB", VoltageB);
        jsonObject.put("VoltageC", VoltageC);
        jsonObject.put("Soc", Soc);
        jsonObject.put("StartTime", StartTime);
        jsonObject.put("EndTime", EndTime);
        jsonObject.put("TotalPower", TotalPower);
        jsonObject.put("ElecMoney", ElecMoney);
        jsonObject.put("ServiceMoney", ServiceMoney);
        jsonObject.put("TotalMoney", TotalMoney);
        jsonObject.put("SumPeriod", SumPeriod);
        jsonObject.put("ChargeDetails", ChargeDetails);

        //推送启动充电结果
        String reqJsonStr = JsonUtil.objToString(jsonObject);
        JSONObject returnInfo = null;

        try {
            returnInfo = JSON.parseObject(HttpClientSslUtils.doPost(url, reqJsonStr));
            Map<String, Object> returnMap = (Map) JSON.parse(String.valueOf(returnInfo));
            String returnSeq = returnMap.get("StartChargeSeq").toString();
            int SuccStat = Integer.parseInt(returnMap.get("SuccStat").toString());
            int FailReason = Integer.parseInt(returnMap.get("FailReason").toString());

            if (returnSeq.equals(StartChargeSeq)) {
                if (0 == SuccStat) {
                    //推送成功
                    log.error("推送成功");
                    return ApsmsResult.success(0, "推送成功", returnMap, "");
                } else if (1 == SuccStat) {
                    //推送失败
                    if (1 == FailReason) {
                        //接受失败
                        log.error("设备接受失败");
                        return ApsmsResult.success(0, "设备接受失败", returnMap, "");
                    } else {
                        return ApsmsResult.success(0, "其他推送失败问题", returnMap, "");
                    }
                } else {
                    return ApsmsResult.success(0, "未获取到推送状态", returnMap, "");
                }
            } else {
                //不匹配
                log.error("订单号不匹配");
                return ApsmsResult.success(0, "", returnMap, "");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return ApsmsResult.error(0, "出现异常", null, "");
        }

//        Map<String, Object> returnMap = new HashMap<String, Object>() {{
//            put("StartChargeSeq", "StartChargeSeq");//充电订单号 格式(“”)
//            put("SuccStat", 0);//操作结果 0-成功 1-失败 格式(0)
//        }};
//        return null;
    }

    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.8 请求停止充电 (由客户归属运营商调用)
     * @Param StartChargeSeq   充电订单号    格式(运营商ID+唯一编码) 27字符
     * @Param ConnectorID   充电设备接口编码    格式(“”)
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/query_stop_charge")
    public ApsmsResult query_stop_charge(String StartChargeSeq, String ConnectorID) {

        //查询当前订单状态
        ChargePileOrderInfo redisInfo = redisCache.getCacheMapValue(RedisKeyConstants.PILE_PORT_ORDER_INFO, StartChargeSeq);

        ChargeCustomOrderInfo chargeCustomOrderInfo =
                chargeCustomOrderInfoMapper.selectChargeCustomOrderInfoByOrderInfoCode(redisInfo.getOrderCode());

        Map<String, Object> returnMap = new HashMap<>();
        if ("2".equals(chargeCustomOrderInfo.getOrderStatus())) {
            returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
            returnMap.put("StartChargeSeqSrat", 4);//充电线订单状态   1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(1)
            returnMap.put("SuccStat", 1);//操作结果 0-成功 1-失败 格式(0)
            returnMap.put("FailReason", 3);//失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
            return ApsmsResult.success(0, "", returnMap, "");
        }

        //下发充电指令
        String deviceCode = ConnectorID.substring(0, ConnectorID.length() - 2);
        String gunPos = ConnectorID.substring(ConnectorID.length() - 2);
        remoteInstructSendService.endCharge(deviceCode, gunPos, "YTSN-CDZ-N01");

        returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
        returnMap.put("StartChargeSeqSrat", 3);//充电线订单状态   1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(1)
        returnMap.put("SuccStat", 0);//操作结果 0-成功 1-失败 格式(0)
        returnMap.put("FailReason", 0);//失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)


//        //1-充电中;2-完成;3-取消;4-故障
//        if ("2".equals(chargeCustomOrderInfo.getOrderStatus())) {
//            returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
//            returnMap.put("StartChargeSeqSrat", 4);//充电线订单状态   1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(1)
//            returnMap.put("SuccStat", 0);//操作结果 0-成功 1-失败 格式(0)
//            returnMap.put("FailReason", 0);//失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
//        }else {
//            if("1".equals(chargeCustomOrderInfo.getOrderStatus())){
//                returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
//                returnMap.put("StartChargeSeqSrat", 2);//充电线订单状态   1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(1)
//                returnMap.put("SuccStat", 1);//操作结果 0-成功 1-失败 格式(0)
//                returnMap.put("FailReason", 4);//失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
//            }else if("4".equals(chargeCustomOrderInfo.getOrderStatus())){
//                returnMap.put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
//                returnMap.put("StartChargeSeqSrat", 5);//充电线订单状态   1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(1)
//                returnMap.put("SuccStat", 1);//操作结果 0-成功 1-失败 格式(0)
//                returnMap.put("FailReason", 2);//失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
//            }
//        }

        return ApsmsResult.success(0, "", returnMap, "");
    }

    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.9 请求停止充电 (向客户归属运营商获取)
     * @Param StartChargeSeq   充电订单号    格式(运营商ID+唯一编码) 27字符
     * @Param StartChargeSeqStat   充电订单状态    1-启动中 2-充电中 3-停止中 4-已结束 5-未知 格式(1)
     * @Param ConnectorID   充电设备接口编码    格式(“”)
     * @Param SuccStat   操作结果 0-成功 1-失败   格式(0)
     * @Param FailReason   停止失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/notification_stop_charge_result")
    public ApsmsResult notification_stop_charge_result(String StartChargeSeq, String StartChargeSeqStat, String ConnectorID,
                                                       String SuccStat, String FailReason) {
        ChargeOtherOrderInfo chargeOtherOrderInfo = chargeOtherOrderInfoMapper.selectChargeOtherOrderInfoByOtherOrderCode(StartChargeSeq);
        String orderStatus = chargeOtherOrderInfo.getOrderStatus();
//        //1-充电中;2-已完成;3-取消;4-故障
//        if ("1".equals(orderStatus)) {
//
//        } else if ("2".equals(orderStatus)) {
//
//        } else if ("3".equals(orderStatus)) {
//
//        } else {
//
//        }

        //设备是否存在
        String deviceCode = ConnectorID.substring(0, ConnectorID.length() - 2);
        String gunPos = ConnectorID.substring(ConnectorID.length() - 2);

        ChargeStationPile pile = chargeStationPileMapper.selectByPrimaryKey(deviceCode);
        ChargeStationPort port = chargeStationPortMapper.selectByPrimaryKey(ConnectorID);
        if (pile == null || port == null) {
            return ApsmsResult.error(0, "", new HashMap<String, Object>() {{
                put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
                put("SuccStat", 1);//操作结果 0-成功 1-失败   格式(0)
                put("FailReason", 1);//停止失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
            }}, "");
        }

        //此设备已离线
        if ("0".equals(pile.getServiceStatus())) {
            return ApsmsResult.error(0, "", new HashMap<String, Object>() {{
                put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
                put("SuccStat", 1);//操作结果 0-成功 1-失败   格式(0)
                put("FailReason", 2);//停止失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
            }}, "");
        }

        //设备已停止充电
        if ("2".equals(orderStatus)) {
            return ApsmsResult.error(0, "", new HashMap<String, Object>() {{
                put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
                put("SuccStat", 1);//操作结果 0-成功 1-失败   格式(0)
                put("FailReason", 3);//停止失败原因 0-无 1-此设备不存在 2-此设备离线 3-设备已停止充电 4~99-自定义 格式(0)
            }}, "");
        }


        //请求停止充电
        Map<String, Object> stringObjectMap = remoteInstructSendService.endCharge(deviceCode, gunPos, "YTSN-CDZ-N01");

        Map<String, Object> returnMap = new HashMap<String, Object>() {{
            put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
            put("SuccStat", 0);//操作结果 0-成功 1-失败 格式(0)
            put("FailReason", 0);//0-无 1-接受失败 格式(0)
        }};
        return ApsmsResult.success(0, "", returnMap, "");
    }

    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.10 推送充电订单信息 (向客户归属运营商获取)
     * @Param StartChargeSeq   充电订单号    格式(运营商ID+唯一编码) 27字符
     * @Param ConnectorID   充电设备接口编码    格式(“”)
     * @Param StartTime   开始充电时间 格式(“yyyy-MM-dd HH:mm:ss”)
     * @Param EndTime    结束充电时间 格式(“yyyy-MM-dd HH:mm:ss”)
     * @Param TotalPower    累计充电量 单位:度 小数点后2位  格式(0.00)
     * @Param TotalElecMoney    总电费 单位:元 小数点后2位  格式(0.00)
     * @Param TotalServiceMoney    总服务费 单位:元 小数点后2位  格式(0.00)
     * @Param TotalMoney    累计总金额 单位:元 小数点后2位  格式(0.00)
     * @Param StopReason    充电结束原因 0-用户手动停止充电 1-客户归属地运营商平台停止充电 2-BMS停止充电 3-充电机设备故障 4-连接器断开 5~99-自定义 格式(0)
     * @Param SumPeriod    时段数 0~32  格式(0)
     * @Param ChargeDetails   充电明细信息 见6.6
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/notification_charge_order_info")
    public ApsmsResult notification_charge_order_info(String StartChargeSeq) {

        String url = "";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("StartChargeSeq", StartChargeSeq);

        ChargeOtherOrderInfo chargeOtherOrderInfo = chargeOtherOrderInfoMapper.selectChargeOtherOrderInfoByOtherOrderCode(StartChargeSeq);
        String ConnectorID = chargeOtherOrderInfo.getPortId();
        String chargeStationName = chargeOtherOrderInfo.getChargeStationName();
        String chargeStationCode = chargeOtherOrderInfo.getChargeStationCode();

        Map<String, Object> returnMap = new HashMap<String, Object>() {{
            put("StartChargeSeq", StartChargeSeq);//充电订单号 格式(“”)
            put("ConnectorID", ConnectorID);//充电设备接口编码  格式("")
            put("ConfirmResult", 0);//确认结果 0-成功 1-争议交易 2~99-自定义 格式(0)
        }};

        return null;
    }

    /*
     * @Author      gaojikun
     * @Date        2024/5/8 14:45
     * @Description    6.11 推送订单对账结果信息 (向客户归属运营商获取)
     * @Param CheckOrderSeq   订单对账流水号    格式(运营商ID+唯一编码) 27字符
     * @Param StartTime   账单开始时间 格式(“yyyy-MM-dd HH:mm:ss”)
     * @Param EndTime    账单结束时间 格式(“yyyy-MM-dd HH:mm:ss”)
     * @Param TotalDisputeOrder    争议订单数量 格式(0)
     * @Param TotalDisputePower    总电量 单位:度 小数点后4位  格式(0.00)
     * @Param TotalDisputeMoney    总金额 单位:元 小数点后2位  格式(0.00)
     * @Param DisputeOrders   订单列表 见下(DisputeOrders-) 格式([])
     * @Param DisputeOrders-StartChargeSeq 充电订单号  格式(运营商ID+唯一编码) 27字符
     * @Param DisputeOrders-TotalPower 累计充电量  单位：度 小数点后2位 格式(0.00)
     * @Param DisputeOrders-TotalMoney 累计总金额  单位：元 小数点后2位 格式(0.00)
     * @Return ApsmsResult
     * @Since version 1.0
     */
    @GetMapping("/check_charge_orders")
    public ApsmsResult check_charge_orders() {
        String url = "";
        String result = HttpUtils.sendGet(url);
        JSONObject jsonObject = JSONObject.parseObject(result);

        Map<String, Object> returnMap = new HashMap<String, Object>() {{
            put("CheckOrderSeq", "CheckOrderSeq");//订单对账流水号 格式(“”)
            put("StartTime", "");//账单开始时间  格式("yyyy-MM-dd HH:mm:ss")
            put("EndTime", "");//账单结束时间  格式("yyyy-MM-dd HH:mm:ss")
            put("TotalDisputeOrder", 0);//争议订单数量 格式(0)
            put("TotalDisputePower", 0.00);//总电量 单位:度 小数点后4位  格式(0.00)
            put("TotalDisputeMoney", 0.00);//总金额 单位:元 小数点后2位  格式(0.00)
            put("DisputeOrders", new ArrayList<Map<String, Object>>() {{
                add(new HashMap<String, Object>() {{
                    put("StartChargeSeq", "");//充电订单号 格式("")
                    put("TotalPower", 0.00);//累计充电量 格式(0.00)
                    put("TotalMoney", 0.00);//累计总金额 格式(0.00)
                    put("DisputeReason", 0);//争议原因 1-交易不存在 2-交易金额错误 3-交易点亮错误 4~99-自定义 格式(0)
                }});
            }});

        }};

        return null;
    }

    /*---------------------------------------------------------------第4部分-数据传输与安全-----------------------------------------------------------------*/
    //所有数据传输接口均采用HTTP(S)/POST


}
